力扣题目
解题思路
java代码
力扣题目:
给定一个整数数组 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]
解题思路:
算法原理:
这道题提供了两种旋转数组的方法。
方法一(rotate1):
- 创建一个与原始数组长度相同的新数组
newArr
。 - 通过计算
(i + k) % n
确定原始数组中每个元素在新数组中的位置,并将其复制到新数组的对应位置。 - 最后将新数组的内容复制回原始数组。
方法二(rotate2):
- 首先计算
k
对数组长度取模,以避免k
大于数组长度的情况。 - 计算
k
和数组长度的最大公约数count
。 - 从
0
到count - 1
,对于每个起始位置start
,进行循环交换操作,直到回到起始位置。
代码分析:
- 在
rotate1
方法中,使用简单的数学计算确定新位置,并复制元素。 rotate2
方法中,通过最大公约数确定循环交换的分组数量,然后在每个分组内进行元素交换。gcd
方法使用递归计算两个数的最大公约数。
时间复杂度:
rotate1
方法的时间复杂度为 ,因为需要遍历数组两次(复制到新数组和从新数组复制回原数组)。rotate2
方法的时间复杂度也为 ,其中外层循环的次数为最大公约数count
,内层循环的次数与分组内的元素数量有关,总体来说也是与数组长度n
成正比。
空间复杂度:
rotate1
方法的空间复杂度为 ,因为创建了一个新的数组。rotate2
方法的空间复杂度为 ,只使用了固定的几个变量,没有额外的数组空间分配。
java代码:
package com.example.myapplication;
public class Leetcode189 {
public void rotate1(int[] nums, int k) {
int n = nums.length;
int[] newArr = new int[n];
for (int i = 0; i < n; ++i) {
newArr[(i + k) % n] = nums[i];
}
System.arraycopy(newArr, 0, nums, 0, n);
}
public void rotate2(int[] nums, int k) {
int n = nums.length;
k = k % n;
int count = gcd(k, n);
for (int start = 0; start < count; ++start) {
int current = start;
int prev = nums[start];
do {
int next = (current + k) % n;
int temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
} while (start != current);
}
}
public int gcd(int x, int y) {
return y > 0 ? gcd(y, x % y) : x;
}
public static void main(String[] args) {
Leetcode189 leetcode189 = new Leetcode189();
int[] nums = new int[]{1, 2, 3, 4, 5, 6, 7};
leetcode189.rotate2(nums, 3);
for (int i : nums) {
System.out.println(i);
}
leetcode189.rotate1(nums, 3);
for (int i : nums) {
System.out.println(i);
}
}
}
更多详细内容同步到公众号,感谢大家的支持!
每天都会给刷算法的小伙伴推送明日一题,并且没有任何收费项