# 189. Rotate Array 反轉陣列 ### 學習用途: 適用於大型數據, 挪動一部分資料 不必開銷 O(n) 空間暫存移動的部分 ### 原地旋轉(不使用額外空間): 1.先將整個數組反轉 2.然後將前k個元素反轉 3.最後將剩餘的元素反轉 ### 工作原理如下: 我們首先處理 k 可能大於數組長度的情況,使用 k %= n。 我們定義了一個輔助函數 reverse(),用於反轉數組的一部分。 然後我們執行三步反轉: - 反轉整個數組 - 反轉前 k 個元素 - 反轉剩餘的元素 這個方法的巧妙之處在於,通過三次反轉,我們實現了`數組的旋轉`,而且是`原地操作`,不需要額外的空間。 ### Complexity - Time complexity: O(n) - Space complexity: O(1) O(1) 空間複雜度意味著算法使用的額外空間是固定的,不隨輸入規模增加。 在數組旋轉問題中,我們通過使用`固定數量的變量`和`原地操作`來實現 O(1) 空間複雜度。 相比之下,創建一個`新數組`來存儲結果`會導致 O(n)` 的空間複雜度。 O(1) 空間複雜度的算法在`處理大規模數據`時特別有優勢,因為它們的內存使用不會隨輸入增加。 ### Code ``` typescript function rotate(nums: number[], k: number): void { const n = nums.length; // 處理 k > n 情況 k %= n; // 處理反轉 const reverse = (start:number, end:number) => { let tmp; for (let i = start; i < end; i++) { tmp = nums[i]; nums[i] = nums[end]; nums[end] = tmp; end--; } } // 三步反轉 reverse(0, n-1); reverse(0, k-1); reverse(k, n-1); }; ``` ### Sample | 步驟 | 操作 | 結果 | |------|------|------| | 初始數組 | - | [1, 2, 3, 4, 5, 6, 7] | | 步驟 1: 反轉整個數組 | reverse(0, n-1) | [`7, 6, 5, 4, 3, 2, 1`] | | 步驟 2: 反轉前 k 個元素 | reverse(0, k-1) | [`5, 6, 7`, 4, 3, 2, 1] | | 步驟 3: 反轉剩餘元素 | reverse(k, n-1) | [5, 6, 7, `1, 2, 3, 4`] | 注意:在這個例子中,k = 3 為什麼這個方法有效: 第一次反轉將所有元素顛倒,**把需要移動到前面的元素放到了數組的前端**,但順序是反的。 第二次反轉將前 k 個元素的**順序糾正**。 第三次反轉將剩餘元素的**順序糾正**。