0189. Rotate Array - chasel2361/leetcode GitHub Wiki

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?

這個題目的重點在於 in-place 的限制,如果沒有這個限制的話最快的做法是把 nums 複製一次接在尾端,然後去頭去尾

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        l = len(nums)
        k %= l
        if k > 0:
            nums[:] = (nums + nums)[l-k:l-k+l]

或者是將尾部剪下,加到前端

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        l = len(nums)
        k %= l
        if k > 0:
            nums[0:l] = nums[-k:] + nums[:-k]

這兩個方法的時間複雜度以及空間複雜度都是 O(1)


那如果有 in-place 的限制,做法就會稍微複雜一點

我最早的想法是,既然要往右輪的話,那就按照 k 的次數把最尾端的數插入到前端即可

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        k %= len(nums)
        for _ in range(k):
            nums.insert(0, nums.pop())

這樣做的時間複雜度是 O(N),空間複雜度是 O(1)。不過因為呼叫 list.insert() 跟 list.pop() 都需要一些時間,速度不夠快

所以研究一下了其他人的寫法,發現可以利用反轉的方式處理,先把整個陣列反轉,在把前半段及後半段反轉即可

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        def reverse(start, end):
            while start < end:
                tmp = nums[start]
                nums[start] = nums[end]
                nums[end] = tmp
                start += 1
                end -= 1
        if k:
            k = k % len(nums)
            reverse(0, len(nums) - 1)
            reverse(0, k - 1)
            reverse(k, len(nums) - 1)

這個方法在反轉的部分應用了 two pointer 的概念,時間複雜度是 O(N),空間複雜度是 O(1)

另外,也可以先創造一個 l 陣列,使其為我們要的結果,再把 l 複製進 nums 裡

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        n = len(nums)
        l = [None] * n
        for i in range(n):
            l[(i + k) % n] = nums[i]
            
        for i in range(n):
            nums[i] = l[i]

這樣的時間複雜度是 O(N),跟前一個方法類似,但空間複雜度較大,為 O(N)