算法题13:轮转数组
题目描述:
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [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:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
0 <= k <= 105
思路:
右移k个位置就是从最后一个元素删掉,然后再放到第一个元素的位置,当k超过数组长度时就可以把k%len(nums),即对数组长度相除取余,
比如题中示例数组长度为7,当k=8时,当k移到7时数组就还原了,其实就是移动了1次。
运行过程中发现不让直接赋值 nums = nums[-k:] + nums[:-k]),感觉这样更简单,非得一步一步调整nums才行。
但是切片这种方式会占用额空间,更合理的是后面的三步反转法。
python
class Solution: def rotate(self, nums: List[int], k: int) -> None: """ Do not return anything, modify nums in-place instead. """ n = len(nums) if k > n: k = k % n # print("here nums[-k:] + nums[:-k]: ", nums[-k:] + nums[:-k]) for i in range(k): temp = nums.pop() nums.insert(0, temp)
结果:

三次反转法:
[1,2,3,4,5,6,7], k = 3
把 [1,2,3,4,5,6,7]变成 [7,1,2,3,4,5,6],可以通过三步反转完成
第一步:把整个数据进行反转
[1,2,3,4,5,6,7] ==> [7,6,5,4,3,2,1]
第二步:反转前k个(3)
[7,6,5,4,3,2,1] ==> [5,6,7,4,3,2,1]
第三步:反转后n - k 个(4)
[5,6,7,4,3,2,1] ==> [5,6,7,1,2,3,4]
对于k >= n的情况,等同于反转k=k%n,即k对n相除取余的情况,因为对于k >= n的情况,由于轮转n次等同于没有轮转,轮转n + 1次等同于轮转1次,
所以依次类推,轮转k次就等同于轮转k对n相除取余次,即k mod n次。
python
class Solution: def rotate(self, nums: List[int], k: int) -> None: """ Do not return anything, modify nums in-place instead. """ def reverse(i, j): while i < j: nums[i], nums[j] = nums[j], nums[i] i += 1 j -= 1 n = len(nums) k %= n # 轮转k次等于轮转k % n次 reverse(0, n - 1) reverse(0, k - 1) reverse(k, n - 1)
java:
class Solution { public void rotate(int[] nums, int k) { int n = nums.length; k %= n; // 轮转k次等同于轮转k % n次 reverse(nums, 0, n - 1); reverse(nums, 0, k - 1); reverse(nums, k, n - 1); } private void reverse(int[] nums, int i, int j) { while (i < j) { int temp = nums[i]; nums[i++] = nums[j]; nums[j--] = temp; } } }
结果:


浙公网安备 33010602011771号