问题描述
给定一个包含数字 {1, 2, 3, 4, 5, 6, 7, 8, 9} 的数组,要求将其随机打乱顺序,生成一个新的数组。
实现思路
要实现数组的随机打乱,核心在于确保每个元素被选中的概率均等,且不会重复选取。这里采用一种基于'交换剔除'的策略,具体步骤如下:
- 初始化新数组:创建一个与原数组长度相同的新数组
newNums,用于存放打乱后的结果。 - 遍历选择:使用循环控制已填充到新数组的元素个数。每次迭代时,我们需要从原数组剩余的未处理部分中随机取出一个元素。
- 随机索引计算:利用
Math.random()生成 [0, 1) 之间的浮点数。乘以剩余可用元素的数量(nums.length - i),再取整,即可得到当前有效范围内的随机下标n。 - 赋值与交换:将原数组下标
n处的元素放入newNums[i]。关键的一步是,为了防止该元素在后续循环中被再次选中,需要将其与原数组末尾(当前未处理区域的最后一个位置)的元素进行交换。
为什么要交换? 如果不做交换,下次随机范围缩小后,我们可能还会抽到同一个下标,导致重复值。通过将已选元素'挪'到已处理区域(数组尾部),我们自然地将它排除在下一次随机选择的范围之外。这样既保证了不重复,又维持了 O(n) 的时间复杂度。
代码示例
下面是完整的 Java 实现,包含主函数测试逻辑,可以直接运行查看效果。
import java.util.Arrays;
public class Demo01 {
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 循环打印多次以验证随机性
for (int i = 0; i < 10; i++) {
int[] ints = randomNumber(nums);
System.out.println(Arrays.toString(ints));
}
}
// 随机打乱数组元素的方法
public static int[] randomNumber([] nums) {
[] newNums = [nums.length];
( ; i < nums.length; i++) {
() (Math.random() * (nums.length - i));
newNums[i] = nums[n];
nums[nums.length - i - ];
nums[nums.length - i - ] = nums[n];
nums[n] = change;
}
newNums;
}
}


