概述
题目背景:
给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组,要求每个数组排列返回的概率相同。
常规思路:暴力求解
将数组中所有的数都放到数据结构 waiting 中,并初始化打乱后的数组shuffle。
循环n次,在第i次循环中(0 < i < n):
- 在waiting中随机抽取一个数num,将其作为打乱后的数组shuffle的第i个元素;
- 从waiting中移除num;
public int[] shuffle() {
//初始化打乱后的数组
int[] shuffled = new int[nums.length];
//存放数组元素的列表list
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < nums.length; ++i) {
list.add(nums[i]);
}
Random random = new Random();
for (int i = 0; i < nums.length; ++i) {
int j = random.nextInt(list.size());
//
shuffled[i] = list.remove(j);
}
System.arraycopy(shuffled, 0, nums, 0, nums.length);
return nums;
}
- 时间复杂度:O(n2) 。需要遍历n个元素,每个元素需要O(n-k)的时间从nums中移除第k个元素。
- 空间复杂度:O(n)。记录初始状态和临时的乱序数组均需要存储 n个元素。
更优思路:洗牌算法
通过洗牌算法可以实现数组的原地乱序:
循环n次,在第i次循环中(0 <= i < n):
- 在 [ i , n ) 中随机抽取一个下标 j;
- 将第 i 个元素与第 j 个元素交换。
public int[] shuffle() {
Random random = new Random();
for (int i = 0; i < nums.length; ++i) {
int j = i + random.nextInt(nums.length - i);
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
return nums;
}
}
- 时间复杂度:O(n) 。只需遍历n个元素即可打乱数组。
- 空间复杂度:O(1)。原地操作,不需要额外空间。
最后
以上就是畅快酸奶为你收集整理的【实用算法】如何随机打乱一个数组?的全部内容,希望文章能够帮你解决【实用算法】如何随机打乱一个数组?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复