189. 旋转数组

https://leetcode-cn.com/problems/rotate-array/

给定一个数组,将数组中的元素向右移动 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) 的原地算法。


把数组中的元素比作学生,坐标比作座位。然后开始换座位,nums[0] 上的同学起身坐到 nums[k+0] 座位上,nums[k+0] 上的同学被挤走, 去到nums[k+k]座位上,反复执行;有一种情况,其中有同学被挤出来后做到了空座位,没人被挤走,此时如果还有同学坐在自己原来的位置上, 那么就要顺着从第二个位置上的同学换位置,直到所有同学做到他最终该坐的位置上,n 个同学换 n 次,用 count 计数,count == len(nums) 时,所有同学完成换座

备注

  • 时间复杂度:O(n),总共移动了 n 次

  • 空间复杂度: O(1)


class Solution(object):
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        length = len(nums)
        k %= length
        if k == 0:
            return
        start = 0
        count = 0

        # n 个位置共需要移动 n 次
        while count < length:
            current = start
            pre = nums[start]

            while True:
                # 将当前位置移动到后k位置
                next_ = (current + k) % length
                tmp = nums[next_]
                nums[next_] = pre

                # 更新当前位置
                current = next_
                pre = tmp

                # 完成一次移动,count加1
                count += 1

                # 当前位置如果是本轮开始位置,说明一件完成一轮
                if current == start:
                    break
            # 如果一轮无法完全所有元素的移动,顺延从第二个位置继续下一轮
            start += 1

class Solution(object):
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        k = k % len(nums)
        self.reverse(nums, 0, len(nums)-1)
        self.reverse(nums, 0, k-1)
        self.reverse(nums, k, len(nums)-1)


    def reverse(self, nums, start, end):
        while start < end:
            nums[start], nums[end] = nums[end], nums[start]
            start += 1
            end -= 1