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

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

在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 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。