题目描述:
给定一个数组,将数组中的元素向右移动 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) 的原地算法。
解题思路:
我这个算法明显是不符合空间复杂度o(1)要求的了,但是当时就是想通过了再说,没有多想一下其他更好的交换算法,下面代码实现的还是老土的新建一个等长的数组然后把数填写到新位置的算法。
参考网上的:
新思路1:
一个一个的移动,就是依次交换k%len次。
新思路2:
假设输入数组的下标是0~ n-1,需要旋转的步数是k,那么按照下面的方法就可以完成旋转数组
(其中reverse表示用双指针交换的方法翻转数组):
step 1 reverse原来的数组。
step 2 reverse 0~ k-1。
step 3 reverse k ~ n-1。
那么得到的新数组就是个旋转数组了。举个例子来说是这样的:
元素组: 1 2 3 4 5 翻转步长:k=3
step 1 reverse原来的数组: 5 4 3 2 1
step 2 reverse 0~ k-1: 3 4 5 2 1
step 3 reverse k ~ n-1。 3 4 5 1 2
最后的【3 4 5 1 2】就是旋转数组的结果了,这种方法的时间复杂度是o(n),空间复杂度是o(1),是非常好的方法了。
代码实现(Java语言):
class Solution {
public void rotate(int[] nums, int k) {
int len = nums.length;
int[] res = new int[len];
int order = 0;
for(int i = len - k%len;i < len;i++){
res[order++] = nums[i];
}
for(int i = 0; i < len - k%len; i++){
res[order++] = nums[i];
}
for(int i = 0;i < len; i++){
nums[i] = res[i];
}
}
}