我是靠谱客的博主 畅快酸奶,最近开发中收集的这篇文章主要介绍【实用算法】如何随机打乱一个数组?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目背景:

给你一个整数数组 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)。原地操作,不需要额外空间。

最后

以上就是畅快酸奶为你收集整理的【实用算法】如何随机打乱一个数组?的全部内容,希望文章能够帮你解决【实用算法】如何随机打乱一个数组?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(90)

评论列表共有 0 条评论

立即
投稿
返回
顶部