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

Java中为二维数组填充不重复随机数的最简实现方法

解决二维数组填充唯一不重复随机数的最简方案

嘿,我来帮你搞定这个问题!首先得先指出你现有代码里的几个小问题:

  • 你定义的二维数组是x,但赋值的时候用了card,变量名不匹配,这肯定会编译报错;
  • 当前的随机数生成逻辑只是按列划分了范围,但完全没做去重处理,所以必然会出现重复值;

接下来直接给你最简、最高效的解决思路:与其每次生成随机数都检查是否已存在(这种方法不仅代码繁琐,数据量大时还容易卡循环),不如先创建一个包含所有需要的唯一数的序列,把它打乱(洗牌),再依次填充到二维数组里。这种方法逻辑简单,还能100%保证不重复。

通用版:生成全局唯一的随机数填充

如果你的需求是整个二维数组里的所有数都唯一,不管具体区间,代码可以这么写:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class UniqueRandom2D {
    public static void main(String[] args) {
        int R = 3; // 替换成你的行数
        int C = 4; // 替换成你的列数
        int[][] card = new int[R][C];
        int totalElements = R * C;
        
        // 1. 创建包含所有唯一数的数组(这里范围是1到总元素数,你可以按需修改)
        Integer[] numbers = new Integer[totalElements];
        for (int i = 0; i < totalElements; i++) {
            numbers[i] = i + 1;
        }
        
        // 2. 打乱数组(用Java内置的洗牌方法,靠谱又省心)
        List<Integer> numList = Arrays.asList(numbers);
        Collections.shuffle(numList);
        
        // 3. 把打乱后的数填充到二维数组里
        int idx = 0;
        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
                card[i][j] = numList.get(idx++);
            }
        }
        
        // 测试输出(可选)
        for (int[] row : card) {
            System.out.println(Arrays.toString(row));
        }
    }
}

适配你原需求的版本:按列划分范围且全局唯一

看你原来的代码是想让每列的数落在[30j+1, 30(j+1)]的区间里,同时所有数唯一。因为每列的区间是不重叠的,我们可以针对每列单独生成区间内的数,打乱后取对应行数的数量填充:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ColumnRangeUnique2D {
    public static void main(String[] args) {
        int R = 2; // 你的行数
        int C = 3; // 你的列数
        int[][] card = new int[R][C];
        
        for (int j = 0; j < C; j++) {
            int start = 30 * j + 1;
            int end = 30 * (j + 1);
            // 生成当前列区间内的所有数
            List<Integer> columnNums = new ArrayList<>();
            for (int num = start; num <= end; num++) {
                columnNums.add(num);
            }
            // 打乱该列的数
            Collections.shuffle(columnNums);
            // 取前R个填充到当前列的各行
            for (int i = 0; i < R; i++) {
                card[i][j] = columnNums.get(i);
            }
        }
        
        // 测试输出
        for (int[] row : card) {
            System.out.println(Arrays.toString(row));
        }
    }
}

为啥你之前的布尔校验法没成功?

大概率是逻辑细节出了问题,比如没正确维护已使用数的标记集合,或者生成随机数的范围计算错误。如果非要用校验法,正确的写法应该是这样(但还是不如洗牌法简洁):

int R = 3;
int C = 4;
int[][] card = new int[R][C];
int maxNum = 30 * C;
boolean[] used = new boolean[maxNum + 1]; // 用索引对应数值,标记是否已使用

for (int i = 0; i < R; i++) {
    for (int j = 0; j < C; j++) {
        int num;
        do {
            // 生成当前列范围内的随机数
            int start = 30 * j + 1;
            int end = 30 * (j + 1);
            num = start + (int)(Math.random() * (end - start + 1));
        } while (used[num]); // 重复就重新生成
        card[i][j] = num;
        used[num] = true; // 标记为已使用
    }
}

总的来说,洗牌法是实现这个需求的最优解:代码少、逻辑清晰、效率高,完全不用操心重复问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:35:22