题目描述
打乱一个没有重复元素的数组。
// 以数字集合 1, 2 和 3 初始化数组。
int[] nums = {1,2,3};
Solution solution = new Solution(nums);
// 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。
solution.shuffle();
// 重设数组到它的初始状态[1,2,3]。
solution.reset();
// 随机返回数组[1,2,3]打乱后的结果。
solution.shuffle();
解决方案
三本水平——利用 java.util.Collections.shuffle()
注意基本类型数组和包装类对象数组之间的转换就好了,计算效率慢;
import java.util.*;
class Solution {
private int[] originNums;
private ArrayList<Integer> numList;
public Solution(int[] nums) {
originNums = nums;
}
/** Resets the array to its original configuration and return it. */
public int[] reset() {
return originNums;
}
/** Returns a random shuffling of the array. */
public int[] shuffle() {
numList = new ArrayList<Integer>(originNums.length);
for(int num : originNums) {
numList.add(num);
}
Collections.shuffle(numList);
return makeDumbResult(numList);
}
public int[] makeDumbResult(List<Integer> numList) {
int[] result = new int[numList.size()];
for (int i=0;i<numList.size();i++) {
result[i] = numList.get(i);
}
return result;
}
}
一本水平——java.util.Random.nextInt 等概率选取
一个元素等概率地选择在数组中出现的位置,且不会重复出现两次及以上。
等概率随机算法的理论推导跟蓄水池算法1十分相似,代码十分简单且高效。
import java.util.*;
class Solution {
private int[] start;
private int[] exe;
private int len;
public Solution(int[] nums) {
start = nums;
exe = start.clone();
len = exe.length;
}
/** Resets the array to its original configuration and return it. */
public int[] reset() {
return start;
}
/** Returns a random shuffling of the array. */
public int[] shuffle() {
Random r = new Random();
int n = len;
// 等概率选取算法核心
while(n>1) {
n--;
int k = r.nextInt(n+1);
int value = exe[k];
exe[k] = exe[n];
exe[n] = value;
}
return exe;
}
}
蓄水池抽样算法——摘抄与问题扩展: https://blog.youkuaiyun.com/landstream/article/details/97051955 ↩︎