# [LeetCode 384. Shuffle an Array ](https://leetcode.com/explore/challenge/card/july-leetcoding-challenge-2021/610/week-3-july-15th-july-21st/3820/) ### Daily challenge Jul 20, 2021 (MEDIAN) >Given an integer array nums, design an algorithm to randomly shuffle the array. All permutations of the array should be equally likely as a result of the shuffling. > >Implement the Solution class: > >* **`Solution(int[] nums)`** Initializes the object with the integer array nums. >* **`int[] reset()`** Resets the array to its original configuration and returns it. >* **`int[] shuffle()`** Returns a random shuffling of the array. :::info **Example 1:** **Input** ["Solution", "shuffle", "reset", "shuffle"] [[[1, 2, 3]], [], [], []] **Output** [null, [3, 1, 2], [1, 2, 3], [1, 3, 2]] **Explanation** Solution solution = new Solution([1, 2, 3]); solution.shuffle(); // Shuffle the array [1,2,3] and return its result. // Any permutation of [1,2,3] must be equally likely to be returned. // Example: return [3, 1, 2] solution.reset(); // Resets the array back to its original configuration [1,2,3]. Return [1, 2, 3] solution.shuffle(); // Returns the random shuffling of array [1,2,3]. Example: return [1, 3, 2] ::: :::warning **Constraints:** * 1 <= nums.length <= 200 * -106 <= nums[i] <= 106 * All the elements of nums are **unique**. * At most 5 * 104 calls **in total** will be made to reset and shuffle. ::: --- ### Approach 1 : Fisher-Yates Algorithm ( 洗牌演算法 ) :book: **`96 ms ( 73.89% )`** **`O(N)`** * **`最初`** 的演算法步驟 : > 想把原始陣列 `nums`隨機排序 > 1. 生成 `0 ~ nums.size()` 之間的隨機數 `j`。 > 2. 將 `nums[j]` 放入新陣列的最後,並移除 `nums[j]`。 > 3. 重複 `第 1、2 步` 直到所有數字都被移除。 > 4. 最後得到的新陣列就是原始陣列的隨機排序。 > > 因為去除 `nums` 的數值時,都需要移位,時間複雜度 **`O(N^2)`**。 * **`現代`** 演算法改進 : > 利用 **`swap()`** 來達到重排的效果,時間複雜度 **`O(N)`**。 > * 原理與最初相同,可以分為兩種方式 > 1. **`i = 0 ~ (N-2)`** ( `nums[N-1]` 無須排列 ) ---> 生成 **`i ~ (N-1)`** 之間的隨機數。 >```cpp=21 > for(int i=0; i<size-1; i++){ > int j = rand() % (size - i); > swap(current[i], current[i+j]); > } >``` > 2. **`i = (N-1) ~ 1`** ( `nums[0]` 無須排列 ) ---> 生成 **`0 ~ i`** 之間的隨機數。 >```cpp=29 > for(int i=size-1; i>0; i--){ > int j = rand() % (i+1); > swap(current[i], current[j]); > } >``` ```cpp=1 class Solution { public: vector<int> current; vector<int> original; Solution(vector<int>& nums) { srand(time(NULL)); current = original = nums; } /** Resets the array to its original configuration and return it. */ vector<int> reset() { current = original; return original; } /** Returns a random shuffling of the array. */ vector<int> shuffle() { // version 1 // int size = current.size(); for(int i=0; i<size-1; i++){ int j = rand() % (size - i); swap(current[i], current[i+j]); } return current; // version 2 /* for(int i=size-1; i>0; i--){ int j = rand() % (i+1); swap(current[i], current[j]); } return current; */ } }; /** * Your Solution object will be instantiated and called as such: * Solution* obj = new Solution(nums); * vector<int> param_1 = obj->reset(); * vector<int> param_2 = obj->shuffle(); */ ```