题目
将包含 n 个元素的数组向右旋转 k 步。
例如,如果 n = 7 , k = 3,给定数组 [1,2,3,4,5,6,7]
,向右旋转后的结果为 [5,6,7,1,2,3,4]
。
注意:
尽可能找到更多的解决方案,这里最少有三种不同的方法解决这个问题。
思路
1 题目比较好理解,但是自己在第一次写的时候却不是那么容易,关键是理清关系
2 对于way 1 首先是k, 简单通俗的将 k为3时, 数组的长度为7,只需要将后三个数移动到数组的前端。k 大于数组的长度时取余
3 way 1 既然是要把后面的数移动到前面 自然想到先将整体的数组翻转
2 翻转 0 k-1的位置
3 翻转 k-1 nums.length - 1的位置
翻转后的两部分的顺序是不变的
翻转函数就比较简单了,记录start和end, 借助中间值调换首位的位置,通知更改start 和 end的值
while循环的条件就是start要小于end ,因为相同的时候整体已经翻转过来了
way 2 如果利用辅助数组的话, nums.clone() 保存了一份拷贝,只需遍历整个数组更改索引位置的值即可,即现在这个位置的值应该存放在哪个位置。位置要取余。空间复杂度o(N)
way 3 直白讲就是转圈的形式,从后往前推,这样推k次
第一次保存下最后的位置,nums.length到0位置的数以前等于前一个数, 第一个数赋值之前保存的末尾值
比较好理解
时间复杂度都是 o(n)
代码
public class Solution {
public void rotate(int[] nums, int k) {
k = k % nums.length;
//(1) new array;
int[] oldNums = nums.clone();
for(int i = 0; i< nums.length;i++){
nums[(i+k)%nums.length] = oldNums[i];
}
//(2) reverse 3 times
// reverse(nums, 0, nums.length-1);
// reverse(nums, 0, k-1);
// reverse(nums, k, nums.length-1);
//(3) move k times
// while(k-->0){
// int tmp = nums[nums.length-1];
// for(int i = nums.length-1; i>0; i--){
// nums[i] = nums[i-1];
// }
// nums[0] = tmp;
// }
}
public void reverse(int[] nums, int start, int end){
while(start < end){
int temp = nums[start];
nums[start] = nums[end];
nums[end]=temp;
start++; end--;
}
}
}