一、題目描述
Given an array, rotate the array to the right by k steps, where k is non-negative.
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
二、題解
方法一:枚舉
算法
- 對於每一次旋轉 ,首尾位置我們採取首尾交換;
- 非首位區域採取前覆蓋後。
* 超時失誤:因爲沒有用戶 k 對 N 取餘,導致超時,例如 時,旋轉 次和旋轉 次的結果是一樣的。
public void rotate(int[] nums, int k) {
int N = nums.length;
k %= N;
for (int i = 0; i < k; i++) {
int last = nums[N-1];
for (int j = N-1; j >= 1; j--) {
nums[j] = nums[j-1];
}
nums[0] = last;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:求餘取差法(新數組)
其實計算機並沒有啥循環 xx,都是通過求餘 % 來達到回到起點的效果。
- 新開闢一個數組 arr,用來記錄每一輪的位置的值。
- 原數組下標 i 與新數組 arr 的下標對應關係是:。
public void rotate(int[] nums, int k) {
int N = nums.length;
k %= N;
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[(i+k)%N] = nums[i];
}
for (int i = 0; i < N; i++)
nums[i] = arr[i];
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法三:三次翻轉
如果你足夠細心,我們會發現樣例中的 k%N
個元素被移動到了前面,而 N - (k%N)
個元素被移動到了上述 k%N
個元素的後面。知道本質,我們可以這樣寫算法:
- 先將
N
個元素全部翻轉。 - 然後翻轉翻轉前
k%N
個元素。 - 最後翻轉後
N - (k%N)
個。
public void rotate(int[] nums, int k) {
int N = nums.length;
k %= N;
reverse(nums, 0, N-1);
reverse(nums, 0, k-1);
reverse(nums, k, N-1);
}
private void reverse(int[] arr, int l, int r) {
while (l < r) {
int t = arr[l];
arr[l++] = arr[r];
arr[r--] = t;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,