Rotate Array
題目
Given an array, rotate the array to the right by k steps, where k is non-negative.
Example 1:
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]
Example 2:
Input: [-1,-100,3,99] and k = 2
Output: [3,99,-1,-100]
Explanation:
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
Could you do it in-place with O(1) extra space?
思路
如果題目沒限制O(1)的空間,這題其實就算簡單,就先建立一個一樣大的array空間,然後把題目給的array一一搬過去到對應的位置,最後再把這個array倒回原本的題目中,但這樣花的額外空間就是O(n)
要限制到O(1), 就是利用一個額外指針先記錄被移動的東西
例如 A搬到B, 要先用個指針把B記住
畫個圖,就可以了解每個回合搬動都會到出發點當作結束
會有幾個回合,就看還剩多下沒有被搬動
看到另外一個解答,是利用翻轉,但這解法實在太神奇,實在很難可以觀察出這樣的模式,我是覺得看看就好。
程式
// O(n)空間
class Solution {
func rotate(_ nums: inout [Int], _ k: Int) {
// 建立一個一樣大的array空間
var newNums = nums
for index in 0 ..< newNums.count {
// 題目給的array一一搬過去到對應位置
newNums[(index + k) % newNums.count] = nums[index]
}
// 再把這個array倒回原本的題目中
nums = newNums
}
}
// O(1)空間
class Solution {
func rotate(_ nums: inout [Int], _ k: Int) {
var count = 0
var start = 0
// 確認所有數字都搬過了
while count < nums.count {
var current = start
var prev = nums[start]
repeat {
let next = (current + k) % nums.count
// 先把目前在接下要搬的東西存起來
let temp = nums[next]
// 開始搬移
nums[next] = prev
prev = temp
current = next
// 表示已搬完一個數字
count += 1
// 只要start還不是current, 表示這個回合還沒搬完
} while (start != current)
// 開始進行下個回合
start += 1
}
}
}
// 神奇翻轉法
class Solution {
func rotate(_ nums: inout [Int], _ k: Int) {
let count = nums.count
let reverse = k % count
nums.reverse()
nums[0..<reverse].reverse()
nums[reverse..<count].reverse()
}
}
複雜度
方法一
時間: O(n), 一個loop搞定。
空間: O(n), 多複製一個array。
方法二
時間: O(n), 雖然看起來有while,裡面又有個repeat, 但其實只跑一回合就可以搞定
空間: O(1), 一些額外指針進行紀錄。
方法三
時間: O(n), 所有元素都要進翻轉過一遍
空間: O(1), 不需要額外空間。
Last updated
Was this helpful?