1. 项目背景与需求解析

华为OD(Outstanding Developer)机试作为华为技术人才选拔的重要环节,其真题设计往往聚焦实际业务场景的抽象与实现。"明日之星选举"作为2026年双机位C卷的考题,本质上是一个典型的票数统计与排序问题,但融合了实时性、数据校验等工程化考量。

1.1 题目核心要求拆解

根据行业惯例和双机位考试特点,此类题目通常包含以下技术要点:

  1. 多候选人票数统计 :需要处理不定数量的候选人及其得票数据
  2. 实时排名计算 :每次投票后需动态更新当前排名
  3. 数据验证机制 :检测无效票(如不存在的候选人ID)
  4. 性能约束 :在C语言环境下需考虑时间复杂度,通常要求O(n)或O(nlogn)解法

1.2 双机位环境特殊性

区别于普通机试,双机位模式增加了:

  • 屏幕共享监控
  • 禁止切换程序
  • 全程录屏存档 这要求代码必须:
// 示例:禁用非标准输入输出的库引用
#include <stdio.h>  // 允许
// #include <graphics.h> // 可能被判定违规

2. 系统设计与数据结构选型

2.1 核心数据结构对比

方案 优点 缺点 适用场景
结构体数组 内存连续访问快 大小固定 已知候选人数量
动态链表 灵活扩展 访问效率低 候选人数量不定
哈希表 O(1)查找 实现复杂 高频查询场景

最终选择 结构体数组+快速排序 方案,原因:

  1. 题目通常给出最大候选人限制(如100人)
  2. 排序操作少于查询操作
  3. 更符合C语言特性

2.2 内存管理设计

typedef struct {
    int id;         // 候选人ID
    char name[50];  // 姓名(根据题目要求可选)
    int votes;      // 得票数
} Candidate;

Candidate candidates[MAX_SIZE];  // 静态分配更安全
int current_count = 0;           // 当前候选人数量

注意:避免使用malloc动态分配,防止内存泄漏导致系统扣分

3. 核心算法实现

3.1 票数统计模块

void vote(int candidate_id) {
    for (int i = 0; i < current_count; i++) {
        if (candidates[i].id == candidate_id) {
            candidates[i].votes++;
            return;
        }
    }
    // 无效票处理
    printf("Invalid candidate ID: %d\n", candidate_id);
}

3.2 实时排名算法

采用快速排序实现O(nlogn)时间复杂度:

int compare(const void *a, const void *b) {
    Candidate *ca = (Candidate *)a;
    Candidate *cb = (Candidate *)b;
    return cb->votes - ca->votes;  // 降序排列
}

void update_ranking() {
    qsort(candidates, current_count, sizeof(Candidate), compare);
}

3.3 输入输出处理

while (scanf("%d", &input) != EOF) {
    if (input == -1) break;  // 常见终止条件
    vote(input);
    update_ranking();
    print_top3();  // 按要求输出当前前三名
}

4. 工程化优化技巧

4.1 输入校验增强

// 检查候选人ID是否重复
int is_duplicate_id(int id) {
    for (int i = 0; i < current_count; i++) {
        if (candidates[i].id == id) return 1;
    }
    return 0;
}

4.2 性能优化策略

  1. 延迟排序 :累计10票才触发排序
  2. 缓存top3 :维护前三名指针避免全排序
  3. 批量处理 :使用缓冲区减少I/O操作
#define BATCH_SIZE 10
int vote_count = 0;

void batch_vote(int id) {
    vote(id);
    if (++vote_count % BATCH_SIZE == 0) {
        update_ranking();
    }
}

5. 双机位环境适配要点

5.1 编码规范要求

  1. 变量命名必须见名知意(禁用temp, a, b等)
  2. 每行代码不超过80字符
  3. 函数不超过50行
  4. 必须添加头文件注释:
/*
 * 功能:候选人票数统计
 * 作者:[考生ID]
 * 日期:2026-xx-xx
 * 版本:1.0
 */

5.2 调试技巧

由于双机位禁止调试器:

  1. 使用printf日志分级:
#define DEBUG 1
#if DEBUG
    printf("[DEBUG] Current top1: %d\n", candidates[0].id);
#endif
  1. 预先准备测试用例数组:
int test_cases[] = {101, 102, 101, 999, 103, -1};

6. 常见问题与解决方案

6.1 段错误排查表

现象 可能原因 解决方案
运行时崩溃 数组越界 检查current_count边界
排序异常 比较函数返回值错误 确认降序/升序逻辑
输出乱码 字符串未终止 确保name末尾有'\0'

6.2 效率优化验证

使用clock()测试关键函数耗时:

clock_t start = clock();
update_ranking();
clock_t end = clock();
printf("Sorting time: %f ms\n", 
      (double)(end - start)*1000/CLOCKS_PER_SEC);

7. 扩展思考方向

  1. 多线程版本 :分离投票接收和统计线程(需加锁)
  2. 持久化存储 :将结果写入文件(注意双机位权限)
  3. 网络版实现 :基于socket通信(非考试要求但可练习)
// 示例:简单的文件存储
void save_results() {
    FILE *fp = fopen("result.txt", "w");
    for (int i = 0; i < current_count; i++) {
        fprintf(fp, "%d,%s,%d\n", 
               candidates[i].id,
               candidates[i].name,
               candidates[i].votes);
    }
    fclose(fp);
}

在实际开发中,我发现在结构体中使用固定大小数组而非指针,虽然会浪费部分内存,但显著降低了内存管理风险。特别是在考试环境下,这种保守但稳定的设计往往比追求极致性能更可靠。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐