You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生成1到20之间5个不重复整数的更优算法求解

原有代码的问题

  • 不要把srand((unsigned)time(NULL))放在函数内部:time函数返回的时间戳精度是秒,如果你1秒内多次调用getRandom,会得到完全一样的随机序列,建议把srand放到程序启动的入口处只执行一次。
  • 去重逻辑有隐患:如果生成了重复值,你直接对i--,但内层循环是遍历整个已生成的数组,一旦出现重复会多次触发i--,可能导致索引异常;另外极端情况如果持续生成重复值,实际循环次数会远超预期,并不是稳定的常数时间执行。
  • 返回静态数组的设计有风险:静态数组的内存是全局共享的,多次调用函数会覆盖上一次的结果,如果你需要保存多组结果很容易出问题。

更优的实现方案

你要生成的是1-20范围内5个不重复的数,范围非常小,用Fisher-Yates洗牌算法是最稳妥的,完全不会有重复问题,逻辑也更简洁:

#include <stdlib.h>
#include <time.h>
#include <stdio.h>

// 调用前确保已经在主函数执行过一次srand((unsigned)time(NULL))
int* getRandom() {
    static int res[5];
    int nums[20];
    // 先生成1-20的有序数组
    for (int i = 0; i < 20; i++) {
        nums[i] = i + 1;
    }
    // 洗牌:只需要洗前5次就能拿到结果
    for (int i = 0; i < 5; i++) {
        // 从[i,19]范围内随机取一个下标
        int r = i + rand() % (20 - i);
        // 交换元素
        int temp = nums[i];
        nums[i] = nums[r];
        nums[r] = temp;
        // 直接取当前位置的元素作为结果
        res[i] = nums[i];
        printf("%d\n", res[i]);
    }
    return res;
}

这个方案的优势

  • 完全没有重复的可能,不需要额外做去重判断,执行次数是固定的25次,比原有实现的最坏情况要稳定很多。
  • 逻辑简洁,不容易出边界错误。

如果你后续需要处理的范围很大(比如要从10000个数里取10个不重复的),那用哈希集合存已经生成的数,判断重复的效率会更高,你当前的场景用洗牌算法就足够了。

内容的提问来源于stack exchange,提问作者Rectanguloid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 07:18:03