leetcode:384. 打乱数组

题目

给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是 等可能 的。
实现 Solution class:

  • Solution(int[] nums) 使用整数数组 nums 初始化对象
  • int[] reset() 重设数组到它的初始状态并返回
  • int[] shuffle() 返回数组随机打乱后的结果

示例:

  1. 输入
  2. ["Solution", "shuffle", "reset", "shuffle"]
  3. [[[1, 2, 3]], [], [], []]
  4. 输出
  5. [null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]
  6. 解释
  7. Solution solution = new Solution([1, 2, 3]);
  8. solution.shuffle(); // 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。例如,返回 [3, 1, 2]
  9. solution.reset(); // 重设数组到它的初始状态 [1, 2, 3] 。返回 [1, 2, 3]
  10. solution.shuffle(); // 随机返回数组 [1, 2, 3] 打乱后的结果。例如,返回 [1, 3, 2]

解答 & 代码

洗牌算法
N 个数的全排列共 N! 种。
遍历数组设置每个位置的数,设当前遍历到下标 i

  • 则当前 [0,...,i-1] 部分已经是随机打乱的,而剩余的 [i,...,n-1] 部分则是待乱序的。因此随机从[i,...,n-1] 部分选择一个数,和第 i 个元素交换,则第 i 个元素填充完毕,继续遍历下一个元素 ```cpp class Solution { private: vector arr; public: Solution(vector& nums) {

    1. arr = nums;

    }

    vector reset() {

    1. return arr;

    }

    vector shuffle() {

    1. int len = arr.size();
    2. vector<int> shuffleArr(arr);
    3. for(int i = 0; i < len; ++i)
    4. {
    5. int idx = rand() % (len - i) + i;
    6. swap(shuffleArr[i], shuffleArr[idx]);
    7. }
    8. return shuffleArr;

    } };

/**

  • Your Solution object will be instantiated and called as such:
  • Solution* obj = new Solution(nums);
  • vector param_1 = obj->reset();
  • vector param_2 = obj->shuffle(); */ `` 复杂度分析:设数组nums` 长为 N
  • 时间复杂度:reset() 操作时间复杂度 O(1),shuffle() 操作时间复杂度 O(N)
  • 空间复杂度:reset() 操作空间复杂度 O(1),shuffle() 操作空间复杂度 O(N)

执行结果:

  1. 执行结果:通过
  2. 执行用时:104 ms, 在所有 C++ 提交中击败了 47.86% 的用户
  3. 内存消耗:88.1 MB, 在所有 C++ 提交中击败了 62.63% 的用户