力扣 hot100 轮转数组 Java 数学&反转&双指针 三种解法 题解
·
题目链接:189. 轮转数组 - 力扣(LeetCode)
题目描述:
给定一个整数数组 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 - 10 <= k <= 105
进阶:
- 尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
- 你可以使用空间复杂度为
O(1)的 原地 算法解决这个问题吗?
思路一:
由于大于i+k可能大于n,会排到-(n-i-k)的位置,不难想到(i+k)%n
代码:
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
int[] ints = new int[n];
for (int i = 0; i < n; i++) {
ints[(i+k)%n]=nums[i];
}
System.arraycopy(ints, 0, nums, 0, n);
}
}
思路二:
通过思路一我们思考可以发现其实把k和n-k的位置全部调换就是反着的答案,最进行一次反转即可。
代码:
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
k=k%n;
reverse(nums,0,n-1);
reverse(nums,0,k-1);
reverse(nums,k,n-1);
}
private void reverse(int[] nums,int start,int end){
while (start<end){
int temp = nums[start];
nums[start] = nums[end];
nums[end]=temp;
start++;
end--;
}
}
}
思路三:
计算数组长度 n 和旋转步数 k 的最大公约数确定数组被拆分的独立环状分组数,然后对每个环从起始位置开始,按(当前索引+k)%n的规则循环替换元素位置,最终在 O (1) 额外空间下完成数组的原地右旋转。
代码:
class Solution {
public void rotate(int[] nums, int k) {
int n=nums.length;
k = k % n;
int cnt = gcd(k,n);
for(int i=0;i<cnt;i++){
int iP = i;
int tP = nums[iP];
do{
int next = (iP+k)%n;
int temp = nums[next];
nums[next]=tP;
tP=temp;
iP=next;
}while (i!=iP);
}
}
private int gcd(int x,int y){
return y>0?gcd(y,x%y):x;
}
}
更多推荐




所有评论(0)