384. Shuffle an Array

本文介绍了一种用于数组洗牌的算法,重点讲解了Fisher-Yates洗牌算法的原理及其实现方式。该算法能够有效地生成数组的所有可能排列,并确保每种排列出现的概率相等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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();
Subscribe to see which companies asked this question

题目的意思是:给定一个数组,将这个数组进行洗牌。洗牌算法,用到了random。

原理如下:
编程珠玑提到将一个数组随机重新洗牌,目的即打乱原有的排列。洗牌算法有以下几种.

Fisher and Yates’ original method

该算法最初是1938年由Ronald A. Fisher和Frank Yates在《Statistical tables for biological, agricultural and medical research》一书中描述,算法生成1-N个数的随机排列的过程如下:

The basic method given for generating a random permutation of the numbers 1–N goes as follows:

Write down the numbers from 1 to N.
Pick a random number k between one and the number of unstruck numbers remaining (inclusive).
Counting from the low end, strike out the kth number not yet struck out, and write it down elsewhere.
Repeat from step 2 until all the numbers have been struck out.(出局)
The sequence of numbers written down in step 3 is now a random permutation of the original numbers.

原始数组中有数字1到N
设原始数组未被标记的数字个数为k,生成一个1到k之间的随机数
取出刚才生成的随机数,将其标记并插入到新的排列数组尾端。
重复过程2直到原始数组中没有未被标记的数字
过程3中生成的新数组就是一个对原始数组的随机排列
证明随机性: 一个元素m被放入第i个位置的概率P = 前i-1个位置选择元素时没有选中m的概率 * 第i个位置选中m的概率,即

这里写图片描述

Modern version of the Fisher–Yates shuffle

改进版的Fisher–Yates shuffle算法是1964年Richard Durstenfeld在 Communications of the ACM volume 7, issue 7中首次提出,相比于原始Fisher-Yates shuffle最大的改进是不需要在步骤3中重复的数未被标记的数字,该算法不再将标记过的数字移动到一个新数组的尾端,而是将随机数选出的数字与排在最后位置的未标记数字进行交换。

代码实现如下:

public class Solution {

    public Solution(int[] nums) {
        array = nums.clone();
        res = nums.clone();
    }

    /** Resets the array to its original configuration and return it. */
    public int[] reset() {
        return array;
    }

    /** Returns a random shuffling of the array. */
    public int[] shuffle() {
        Random random = new Random();  
        random.nextInt();
        int len = res.length;
        for(int i = 0; i < len; i++)
        {
            int change = random.nextInt(len-i);
            swap(res, i, change);

        }
        return res;
    }
    private void swap(int[] a, int i, int change){
        int tmp = a[i];
        a[i] = a[change];
        a[change] = tmp;
    }

    private int[] array;
    private int[] res;
}

/**
 * Your Solution object will be instantiated and called as such:
 * Solution obj = new Solution(nums);
 * int[] param_1 = obj.reset();
 * int[] param_2 = obj.shuffle();
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值