LeetCode 384 打乱数组

题目链接:LeetCode 384 打乱数组

题目大意:
给你一个整数数组\(nums\),设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是等可能的。

题解:
参考自LeedCode官方题解
首先,我们考虑如何随机打乱一个数组。
不妨设数组\(nums\),其长度为\(n\)。我们可以使用如下方法打乱:

  • 将数组中所有的数都放到数据结构\(waiting\)中,并初始化打乱后的数组\(shuffle\)
  • 循环\(n\)次,在第\(i\)次循环中\((0 \leq i < n)\)
    • \(waiting\)中随机抽取一个数\(num\),将其作为打乱后的数组\(shuffle\)的第\(i\)个元素;
    • \(waiting\)中移除\(num\)

对于原数组\(nums\)中的数\(num\)来说,被移动到打乱后的数组的第\(i\)个位置的概率为:

\[p[i]= \left\{ \begin{array}{l} (\frac{n-1}{n} \times \frac{n-2}{n-1} \times ... \times \frac{n-i}{n-i+1}) \times \frac{1}{n-i} = \frac{1}{n}, i>0 \\ \frac{1}{n}, i = 0 \end{array} \right. \]

因此,对于原数组\(nums\)中的任意一个数,被移动到打乱后的数组的任意一个位置的概率都是相同的。

class Solution {
private:
    vector<int> nums;
    vector<int> orgins;

public:
    Solution(vector<int>& nums) {
        this->nums = nums;
        this->orgins.resize(nums.size());
        copy(nums.begin(), nums.end(), orgins.begin());
    }
    
    vector<int> reset() {
        copy(orgins.begin(), orgins.end(), nums.begin());
        return nums;
    }
    
    vector<int> shuffle() {
        vector<int> shuf(orgins.size());
        copy(orgins.begin(), orgins.end(), shuf.begin());
        for (int i = 0; i < orgins.size(); ++i) {
            int index = rand() % shuf.size();
            vector<int>::iterator it = shuf.begin();
            advance(it, index);
            nums[i] = *it;
            shuf.erase(it);
        }
        return nums;
    }
};
posted @ 2022-02-06 21:35  ZZHHOOUU  阅读(27)  评论(0编辑  收藏  举报