给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?
方法:数组翻转
双指针,左指针右移,右指针左移翻转数组
题解转载自Leetcode官方
该方法基于如下的事实:当我们将数组的元素向右移动 k 次后,尾部 k mod n 个元素会移动至数组头部,其余元素向后移动 k mod n 个位置。
该方法为数组的翻转:我们可以先将所有元素翻转,这样尾部的 k mod n 个元素就被移至数组头部,然后我们再翻转 [0,k mod n−1] 区间的元素和 [k mod n,n−1] 区间的元素即能得到最后的答案。
class Solution {
public void rotate(int[] nums, int k) {
int len = nums.length;
k%=len;
nums=reverse(nums,0,len-1);
//第k个数的下标是k-1而不是k!
nums=reverse(nums,0,k-1);
nums=reverse(nums,k,len-1);
}
//双指针,左指针右移,右指针左移翻转数组
public int[] reverse(int[] nums, int start, int end){
while(start<end){
int temp=nums[start];
nums[start]=nums[end];
nums[end]=temp;
//左指针右移,右指针左移
start++;
end--;
}
return nums;
}
}
注意:利用双指针+统一的reverse函数可以避免写重复代码及写错
class Solution {
public void rotate(int[] nums, int k) {
int len = nums.length;
k%=len;
if(k==0) return;
//反转数组
for(int i=0;i<len/2;i++){
int temp = nums[i];
nums[i]=nums[len-1-i];
nums[len-1-i]=temp;
}
for(int i=0;i<k/2;i++){
int temp = nums[i];
nums[i]=nums[k-1-i];
nums[k-1-i]=temp;
}
for(int i=len/2;i<3*len/4-1/2;i++){
int temp = nums[i];
nums[i]=nums[3*len/2-1-i];
nums[3*len/2-i-1]=temp;
}
}
}