題目
題目來自LeetCode
給定一個數組,將數組中的元素向右移動k
個位置,其中k
是非負數。
示例 1:
輸入: [1,2,3,4,5,6,7] 和 k = 3
輸出: [5,6,7,1,2,3,4]
解釋:
向右旋轉 1 步: [7,1,2,3,4,5,6]
向右旋轉 2 步: [6,7,1,2,3,4,5]
向右旋轉 3 步: [5,6,7,1,2,3,4]
示例 2:
輸入: [-1,-100,3,99] 和 k = 2
輸出: [3,99,-1,-100]
解釋:
向右旋轉 1 步: [99,-1,-100,3]
向右旋轉 2 步: [3,99,-1,-100]
說明:
- 儘可能想出更多的解決方案,至少有三種不同的方法可以解決這個問題。
- 要求使用空間複雜度爲
O(1)
的原地算法。
實現
方法1
一個比較典型的旋轉問題
以1234567
,k=3
舉例:
先全部旋轉reverse(0, length-1)
,結果:
7654321
然後旋轉前k
個數字,reverse(0, k-1)
,結果:
567 4321
最後旋轉剩餘數字:,reverse(k, length-1)
,結果:
567 1234
用代碼實現:
var rotate = function (nums, k) {
let length = nums.length;
// 處理k<n的情況
k = k % length;
// 旋轉
function reverse(arr, start, end) {
while (start < end) {
[arr[start], arr[end]] = [arr[end], arr[start]];
start++;
end--;
}
}
reverse(nums, 0, length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, length - 1);
return nums
};
要注意k = k % length
這行代碼,有兩個作用,一個是防止數組的長度小於k
時出現錯誤,另一個是減少移動的次數
方法2
可以直接利用JS內置的插入的方法,它會自動將數組的序號更新(我怎麼把這個方法忘了)
var rotate = function (nums, k) {
for (let i = 0; i < k; i++) {
nums.unshift(nums.splice(nums.length-1, 1)[0])
}
return nums
};
方法3
又想了一個特笨的方法
還是以1234567
,k=3
舉例
先從後向前進行第一輪移動,每相鄰兩項進行換位,結果是:
7123456
然後再進行第二輪移動,類似的,結果是:
6712345
k
決定了移動的次數:
var rotate = function (nums, k) {
while (k) {
for (let i = nums.length - 1; i > 0; i--) {
[nums[i], nums[i-1]] = [nums[i-1], nums[i]]
}
k--;
}
return nums
};
應該還有其他的方法,比如通過遞歸實現,回頭重新的時候再想吧。