题目描述
给定一个整数数组
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 <=
-
<= nums[i] <=
- 1
0 <= k <=
进阶:
- 尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
- 你可以使用空间复杂度为
O(1)
的 原地 算法解决这个问题吗?
解题思路
要将数组中的元素向右轮转 k
个位置,可以使用几种不同的方法:
-
使用额外空间(数组复制):
复制原数组的部分到一个新的数组中,并将它们合并以得到结果。这种方法简单,但使用了额外的空间。 -
使用反转数组:
这种方法不使用额外的空间(O(1) 空间复杂度),通过数组反转实现轮转。具体步骤是:反转后n-k
个元素;反转前k
个元素;反转整个数组。 -
使用环状替换(原地算法):
这是一种在 O(n) 时间复杂度和 O(1) 空间复杂度下的原地算法。通过循环移动元素,将每个元素放到它最终的位置。
复杂度分析
-
方法 1:通过创建新数组并将元素放置到新位置,然后将结果复制回原数组。这种方法简单但需要额外的空间。
-
方法 2:通过反转整个数组,然后分别反转前
k
个元素和后n-k
个元素来实现轮转。这种方法不使用额外的空间(O(1) 空间复杂度),且时间复杂度为 O(n)。 -
方法 3:使用环状替换算法,通过逐个移动元素到其最终位置来实现轮转。这种方法也是 O(n) 时间复杂度,并且 O(1) 空间复杂度。
代码实现
package org.zyf.javabasic.letcode.hot100.ordinaryarray;
import java.util.Arrays;
/**
* @program: zyfboot-javabasic
* @description: 轮转数组
* @author: zhangyanfeng
* @create: 2024-08-21 22:22
**/
public class RotateSolution {
public void rotate1(int[] nums, int k) {
int n = nums.length;
k = k % n; // 处理 k 大于数组长度的情况
int[] result = new int[n];
for (int i = 0; i < n; i++) {
result[(i + k) % n] = nums[i];
}
// 复制结果数组到原数组
System.arraycopy(result, 0, nums, 0, n);
}
public void rotate2(int[] nums, int k) {
int n = nums.length;
k = k % n; // 处理 k 大于数组长度的情况
reverse(nums, 0, n - 1); // 反转整个数组
reverse(nums, 0, k - 1); // 反转前 k 个元素
reverse(nums, k, n - 1); // 反转后 n - k 个元素
}
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--;
}
}
public void rotate3(int[] nums, int k) {
int n = nums.length;
k = k % n; // 处理 k 大于数组长度的情况
int count = 0; // 记录移动的元素数量
for (int start = 0; count < n; start++) {
int current = start;
int prevValue = nums[start];
do {
int nextIndex = (current + k) % n;
int temp = nums[nextIndex];
nums[nextIndex] = prevValue;
prevValue = temp;
current = nextIndex;
count++;
} while (start != current);
}
}
public static void main(String[] args) {
RotateSolution solution = new RotateSolution();
// 测试用例 1
int[] nums1 = {1, 2, 3, 4, 5, 6, 7};
solution.rotate3(nums1, 3);
System.out.println(Arrays.toString(nums1)); // 输出: [5, 6, 7, 1, 2, 3, 4]
// 测试用例 2
int[] nums2 = {-1, -100, 3, 99};
solution.rotate3(nums2, 2);
System.out.println(Arrays.toString(nums2)); // 输出: [3, 99, -1, -100]
}
}
具体可参考:https://zyfcodes.blog.csdn.net/article/details/141401712