C#实现指定范围内不重复随机数生成的四种方法

山间有风
山间有风
发布时间:2026-10-13 | 6人浏览过
原创

在C#开发中,生成不重复随机数是常见的需求。本文将深入解析四种主流实现方案,从基础的遍历查重到高效的空间置换算法,并提供可运行的核心代码片段,协助解决此技术难题。

问题背景与挑战

C#标准库中的 System.Random 类提供的 Next() 方法只能生成单个随机整数,本身不具备去重机制。若需获取一个范围内的不重复序列(如1到100中取10个不重复数字),直接循环调用往往会导致碰撞,需要通过额外的逻辑进行过滤或管理已选数据状态。

准备条件与通用参数

  1. 目标范围:设定最小值 minValue 和最大值 maxValue。
  2. 抽取数量:确定需要生成的不重复随机数个数 count。
  3. 依赖组件:主要使用 System 命名空间下的 Random 类;部分方法涉及 System.Collections 或 System.Linq。

实现方法详解

第1步:基础循环与内部查重

这是最直观的逻辑:每次生成一个随机数后,遍历当前结果数组检查是否已存在。如果已存在则忽略本次生成并重新尝试(通过递减索引实现重试)。

  • 入口/动作:初始化一个长度为 Number 的整型数组,外层循环控制生成次数,内层循环用于比对历史数据。
  • 关键逻辑:当发现冲突(num > 0)时,通过 j-- 使外层循环回退,确保最终填满有效数组。
  • 代码示例
public int[] GetRandomArray(int Number, int minNum, int maxNum)
{
    int j;
    int[] b = new int[Number];
    Random r = new Random();
    for (j = 0; j < Number; j++)
    {
        // 包含上限
        int i = r.Next(minNum, maxNum + 1);
        int num = 0;
        // 检查是否与之前生成的数重复
        for (int k = 0; k < j; k++)
        {
            if (b[k] == i)
            {
                num++;
                break; // 只要发现重复即可提前跳出
            }
        }
        if (num == 0)
        {
            b[j] = i;
        }
        else
        {
            // 发生重复,本次计数作废,重新生成
            j--;
        }
    }
    return b;
}

第2步:数组置换法(推荐高效方案)

该方法的思路类似于“抽彩票”或“洗牌”。先建立一个包含所有候选数的数组,每次随机抽取一个位置,将该位置的元素放入结果集,并将该位置替换为末尾元素,同时将可选池的大小减一。这种方法时间复杂度低,且不产生重复风险。

  • 操作对象:index 数组作为备选池,result 数组存储结果。
  • 参数说明:site 代表当前可选池的有效上限。
int[] index = new int[15]; 
// 初始化备选池 0-14
for (int i = 0; i < 15; i++) 
    index[i] = i; 

Random r = new Random(); 
int[] result = new int[10]; 
int site = 15; 
int id;

// 只需循环10次
for (int j = 0; j < 10; j++) 
{ 
    // 在当前可选范围内随机选一个索引
    id = r.Next(0, site); 
    result[j] = index[id]; 
    // 用最后一个元素填补当前位置,移除已选项
    index[id] = index[site - 1]; 
    // 缩小可选池
    site--; 
}

第3步:集合去重法

利用字典结构的唯一性键值特性(如 HashSet`1 或旧版的 Hashtable)。将生成的随机数作为Key加入集合,直到集合大小达到目标数量。由于Key不可重复,因此自然保证了随机数的唯一性。

  • 注意:原版代码使用了 Hashtable 且校验 ContainsValue,这在现代 .NET 中效率较低(应校验 Key)。推荐使用 HashSet<int>。
// 推荐写法:使用 HashSet<int>
HashSet<int&gths = new HashSet<int>();
Random rm = new Random();
int targetCount = 10;

while (hs.Count < targetCount) {
    int val = rm.Next(1, 100); // 指定范围
    hs.Add(val); // 如果已存在则返回false,不会增加Count
}
// 转换回数组或其他形式
int[] results = hs.ToArray();

第4步:LINQ 简化方案

如果性能不是极端敏感的场景,可以使用 LINQ 进行区间映射和去重,代码最为简洁,但需注意大数据量时的内存开销。

using System.Linq;

// 假设范围是 1 到 100,取 10 个
var random = new Random();
var range = Enumerable.Range(1, 100);
var result = range.OrderBy(x => random.Next()).Take(10).ToArray();

完成判断与总结

以上即为 C# 生成不重复随机数的详细内容。对于小规模数据,简单的循环查重足够适用;追求性能时应选用数组置换法(Fisher-Yates Shuffle 的变体);而在编写脚本或快速原型时,LINQ 方案能极大提升开发效率。更多关于 C# 算法优化的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表