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

如何避免rand()生成重复随机数?if else结构是否可行?

无重复随机数的实现方案

仅用if else确实能实现不重复的随机数生成,但效率不算高,更推荐用洗牌算法来处理,下面具体说明两种方式:

一、用if else+重试的方式实现

思路是:每次生成随机数后,遍历已经存入数组的元素,检查是否重复。如果重复,就重新生成随机数,直到拿到不重复的值。

需要注意的是,你的原代码里用了time(NULL)但没包含<time.h>,编译时会有警告,记得补上。修改后的代码如下:

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

int main(int argc, char *argv[]) {  
    srand(time(NULL));
    int i, j;
    int dizi[20];

    for (i = 0; i < 20; i++) {
        int num;
        int is_duplicate;
        do {
            num = rand() % 20;
            is_duplicate = 0;
            // 检查当前数是否和之前的重复
            for (j = 0; j < i; j++) {
                if (dizi[j] == num) {
                    is_duplicate = 1;
                    break;
                }
            }
        } while (is_duplicate); // 重复就重试
        dizi[i] = num;
    }   

    for (i = 0; i < 20; i++) {
        printf("%d\n", dizi[i]);
    }   
    
    return 0;
}

这种方法的问题在于:当数组快填满时(比如生成第19、20个数时),重复的概率会非常高,可能需要多次调用rand()才能拿到未出现过的数,效率较低。

二、更高效的洗牌算法(Fisher-Yates)

思路是:先初始化一个包含0到19的有序数组,然后通过随机交换数组元素的位置,得到一个无重复的随机序列。这种方法的时间复杂度是O(n),效率远高于重试法。

代码示例:

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

int main(int argc, char *argv[]) {  
    srand(time(NULL));
    int i;
    int dizi[20];

    // 先初始化数组为0到19的有序序列
    for (i = 0; i < 20; i++) {
        dizi[i] = i;
    }

    // Fisher-Yates洗牌:从后往前交换
    for (i = 19; i > 0; i--) {
        // 生成0到i的随机索引
        int rand_idx = rand() % (i + 1);
        // 交换当前元素和随机索引的元素
        int temp = dizi[i];
        dizi[i] = dizi[rand_idx];
        dizi[rand_idx] = temp;
    }

    // 输出结果
    for (i = 0; i < 20; i++) {
        printf("%d\n", dizi[i]);
    }   
    
    return 0;
}

这种方法能保证每个数只出现一次,且随机分布均匀,没有重试的开销,是生成无重复随机序列的最优方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:05:24