本周每日一题 题目
11-22 lc 384. 打乱数组
- 这题我把它想得复杂了,以为reset是返回到上一个状态,所以还记录下了如何洗牌,所以多了一个swapRec的数组,还多了reset中被注释的方法,这个请忽略
- 直接保存一个最初的数组即可,注意java的语言特点,所以这里得用深拷贝,可以用system.copyofarray,也可以用clone方法,前者要好一些其实,省gc的时间
- 洗牌的逻辑是,遍历数组,使得当前位置与前面的随机一个位置交换
- 这里的概率如何证明洗牌的结果公平?
- 其实很简单,之前做过一题,叫全排列。那题给定一个数组,没有重复元素,要求输出所有的全排列
- 那题的一个简单的做法就是swap
- 而我们这里的到底跟谁交换是等概率的,是随机的,所以相当于每个都有尝试
- 既然swap能够全排列,那么等概率随机swap得到的每个结果都是等概率的
- 证明完毕
class Solution {
private int[] swapRec = null;
private int[] nums = null;
private int[] original = null;
private int n = -1;
public Solution(int[] nums) {
this.n = nums.length;
this.nums = nums.clone();
this.original = nums.clone();
this.swapRec = new int[this.n];
}
public int[] reset() {
nums = original.clone();
return nums;
}
public int[] shuffle() {
Random rand = new Random();
for(int i=0; i<this.n; i++){
int j = rand.nextInt(i+1);
swapRec[i] = j;
swap(nums,i,j);
}
return nums;
}
private void swap(int[] nums,int i, int j){
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}