LeetCode189 旋转数组

90 阅读1分钟

leetcode.cn/problems/ro…

image.png

解法一:暴力法

以倒数第k个位置为分界点,将前后两半子数组调换一下,组成新数组即为答案

func rotate(nums []int, k int)  {
    if k > len(nums) {
        k = k%len(nums)
    }
    lastK := nums[len(nums)-k:] // 倒数k个元素
    front := nums[:len(nums)-k] // 前半部分
    res := append(lastK, front...) // 置换两部分子数组
    for i:=0; i<len(nums); i++{ // 答案更新到原数组上
        nums[i] = res[i]
    }
}

好家伙,一个暴力法耗时击败100%?

image.png

但显然,空间复杂度有待优化,这里可以考虑原地置换数组,省去上面申请的3个临时数组lastK, front, res

解法二:反转数组

向右轮转k个元素,其实就是把分别包含前 len(nums)-k个元素和后 k个元素的两个子数组交换位置,子数组内部元素要保持原来的顺序不变,

这样的话,先逆置整个数组,这样两个子数组就互换位置了,但是这样两个子数组内部的元素顺序也逆置了,那么就分别逆置一次两个子数组里的元素,这样子数组就恢复原来的顺序,轮换就完成了。

image.png

func rotate(nums []int, k int)  {
    if k > len(nums) {
        k = k%len(nums)
    }
    slices.Reverse(nums) // 反转整个数组
    slices.Reverse(nums[:k]) // 反转前k个元素
    slices.Reverse(nums[k:]) // 反转后len-k个元素
}

不调内部包能否手撕?安排!

解法三:原地反转数组,双指针法

func rotate(nums []int, k int)  {
    if k > len(nums) {
        k = k%len(nums)
    }
    reverseList(nums)
    reverseList(nums[:k])
    reverseList(nums[k:])
}

func reverseList(nums []int) {
    left, right := 0, len(nums)-1
    for left < right{
        nums[left], nums[right] = nums[right], nums[left]
        left++
        right--
    }
}