C#数组重复元素检测与替换方法(数独开发场景)
解决数独列填充时的重复数字问题
首先,直接用Random.Next()生成数字会重复,事后检测替换不仅逻辑繁琐,还可能出现效率问题(比如快填满时多次重试)。更高效的方式是先生成1-9的完整序列,再打乱顺序填充,这样天然保证每列数字不重复。
优化后的实现方案
推荐使用Fisher-Yates洗牌算法打乱1-9的序列,这是行业内标准的公平洗牌方法,效率高且逻辑清晰。
首先在类中声明一个全局的Random实例(避免循环内多次创建导致随机序列重复):
private Random _random = new Random();
然后修改你的populateColumns方法:
void populateColumns(int[][] arr) { // 遍历每一列(arr中的每个子数组对应一列) foreach (var column in arr) { // 生成1到9的完整数字列表 var numList = Enumerable.Range(1, 9).ToList(); // 打乱列表顺序 ShuffleList(numList); // 将打乱后的数字填充到列中 for (int i = 0; i < column.Length; i++) { column[i] = numList[i]; Console.Write(column[i]); } Console.WriteLine(); // 换行区分不同列,方便调试 } } // Fisher-Yates洗牌算法实现 void ShuffleList<T>(List<T> list) { int count = list.Count; while (count > 1) { count--; int randomIndex = _random.Next(count + 1); // 交换元素位置 T temp = list[randomIndex]; list[randomIndex] = list[count]; list[count] = temp; } }
原代码的问题说明
- 循环逻辑冗余:你原来的
l和j变量可以简化,直接遍历arr的每个子数组即可,无需额外的索引变量。 - 随机数生成隐患:如果你的
Num()方法每次都新建Random实例,短时间内多次调用会因种子相同生成重复序列,导致重复数字概率更高。
备选方案:重复检测替换(不推荐)
如果一定要用“生成-检测-替换”的逻辑,也可以实现,但效率较低,仅作参考:
void populateColumnsWithDuplicateCheck(int[][] arr) { foreach (var column in arr) { for (int i = 0; i < column.Length; i++) { int newNum; // 循环生成直到找到未重复的数字 do { newNum = _random.Next(1, 10); // 生成1-9的随机数 } while (column.Take(i).Contains(newNum)); column[i] = newNum; Console.Write(newNum); } Console.WriteLine(); } }
这种方法在列快填满时,可能需要多次重试才能找到可用数字,极端情况下甚至会陷入无意义循环,因此优先推荐洗牌法。
内容的提问来源于stack exchange,提问作者goldern
相关产品推荐
相关产品推荐

