leetcode384. Shuffle an Array

栏目: 编程工具 · 发布时间: 4年前

内容简介:实现shuffle和reset方法,分别能够完成数组的随机打乱和还原。随机打乱即该数组中元素的所有排列组合结果都能够以等比例的概率输出。直观的思路来说,我们会将数组复制一份,并根据数组的长度来生成随机数,并获得该随机数下标上的值放在新的位置上。本文将详细讲解一下网上的另一种解法,即该算法的步骤如下:

题目要求

Shuffle a set of numbers without duplicates.

Example:

// Init an array with set 1, 2, and 3.
int[] nums = {1,2,3};
Solution solution = new Solution(nums);

// Shuffle the array [1,2,3] and return its result. Any permutation of [1,2,3] must equally likely to be returned.
solution.shuffle();

// Resets the array back to its original configuration [1,2,3].
solution.reset();

// Returns the random shuffling of array [1,2,3].
solution.shuffle();

实现shuffle和reset方法,分别能够完成数组的随机打乱和还原。随机打乱即该数组中元素的所有排列组合结果都能够以等比例的概率输出。

思路和代码

直观的思路来说,我们会将数组复制一份,并根据数组的长度来生成随机数,并获得该随机数下标上的值放在新的位置上。本文将详细讲解一下网上的另一种解法,即 Fisher–Yates 算法,该算法能够用O(n)的时间随机打乱一个数组。

该算法的步骤如下:

  1. 从数组中随机选择一个数字,与数组最后一个数字交换
  2. 从前 n-1 个元素中随机选择一个数字,与第 n-1 个数字交换
  3. 从前 n-2 个元素中随机选择一个数字,与第 n-2 个数字交换...

重复以上步骤,直到数组第一个元素。

下面解释一下证明,即为何每个该结果是等概率的排列组合结果。

第一步操作,对于数组中所有的元素,均有1/n的概率交换到最后一个位置上

第二步操作可以分为两种场景。

((n-1)/n) * (1/n-1) = 1/n
((n-1)/n * (1/n-1)) = 1/n

第三步操作可以分为三种场景:

  • 场景一:选中进行交换的元素为最后一个元素,则该元素被选中的概率等于该元素被交换到前面n-2个元素的概率乘以该元素在当前n-1个元素中被选中的概率。该元素没有被交换到前面n-2个元素只有两种可能,即位于原来的位置,或是被交换到倒数第二个位置,因此交换到前面n-2个元素的概率为 (1 - 1/n - (n-1)/n * 1 / (n-1)) = (n-2) / n , 因此最终概率为 (n-2)/n * 1/(n-2) = 1/n
  • 场景二:选中进行交换的元素为倒数第二个元素,则该元素被选中的概率等于该元素被交换到前面n-2个元素的概率乘以该元素在当前n-2个元素中被选中的概率。该元素没有被交换到前面n-2个元素只有两种可能,即该元素被交换至最后一个元素,或是依然位于原来的位置,因此交换到前面n-2个元素的概率为 (1 - 1/n - (n-1)/n * 1 / (n-1)) = (n-2) / n , 因此最终概率为 (n-2)/n * 1/(n-2) = 1/n
  • 场景三:选中进行交换的元素为剩余的其他元素,则该元素被选中的概率没有被交换到最后两个位置上,最终概率也可以计算出来为 1/n

综上,这种方法能够保证每一个元素可以等概率出现在任何位置上。代码如下:

private int[] nums;
    private Random random;
    public Solution(int[] nums) {
        this.nums = nums;
        random = new Random();
    }
    
    /** Resets the array to its original configuration and return it. */
    public int[] reset() {
        return this.nums;
    }
    
    /** Returns a random shuffling of the array. */
    public int[] shuffle() {
        if(nums == null) return null;
        int[] result = nums.clone();
        for(int j = 1; j < result.length; j++) {
            int i = random.nextInt(j + 1);
            swap(result, i, j);
        }
        return result;
    }
    
    private void swap(int[] a, int i, int j) {
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

以上所述就是小编给大家介绍的《leetcode384. Shuffle an Array》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据结构与算法分析

数据结构与算法分析

韦斯 / 机械工业 / 2007-1 / 55.00元

本书是国外数据结构与算法分析方面的标准教材,使用最卓越的Java编程语言作为实现工具讨论了数据结构(组织大量数据的方法)和算法分析(对算法运行时间的估计)。   随着计算机速度的不断增加和功能的日益强大,人们对有效编程和算法分析的要求也在增长。本书把算法分析与最有效率的Java程序的开发有机地结合起来,深入分析每种算法,内容全面、缜密严格,并细致讲解精心构造程序的方法。   第......一起来看看 《数据结构与算法分析》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具