描述
给定一个数组,将数组中的元素向右移动 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) 的原地算法。
解题思路:
解题思路有很多种,下面讲述两种比较巧妙的解法:
1.使用原地替换的方法,首先使用tmp记录数组第一个值,从第一个元素开始,不断的swap(tmp,nums[i]),其中i是tmp值的目标位置;这里要注意的一个情况就是移动的步数k是数组长度的因子,这样会出现重复循环的情况,需要一个标志位来标识这种情况从而打破循环;
void rotate(vector & nums, int k) { if(nums.empty()) { return; } k %= nums.size(); int len = nums.size(); int c = len; int tmp = nums[0]; int i=0; int mark = i; while(c-- >= 0) { i = (i + k) >= len ? i + k - len : i+k; swap(nums[i],tmp); if(c > 0 && i == mark) { ++i; tmp = nums[i]; mark = i; } } }
2.通过观察目标数组可以发现,目标数组的前k位是原数组的最后n-k位,所以通过反转数组实现,首先反转前n-k个元素,再反转后k个元素,最后反转整个数组实现。
Solution { void rotate(vector & nums, int k) { if(nums.empty()) { return; } int len = nums.size(); if(k % len == 0) { return; } k %= len; reverse(nums,0,len - k - 1); reverse(nums,len -k,len - 1); reverse(nums,0,len-1); } void reverse(vector & nums,int start,int end) { while(start < end) { swap(nums[start],nums[end]); ++start; --end; } } };