给定一个整数数组 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
解题思路
题目都意思是我们要转动的我们的数组 就是里面的元素从左到右移动 循环往复 最后一个元素移动到第一个其他的依次移动一个下标 还要根据我们的参数移动几次 去处理转几次
-
第一种办法暴力枚举
public void test(int[] nums, int k) {
// 添加边界检查
if (nums == null || nums.length <= 1 || k <= 0) {
return;
}
// 处理k大于数组长度的情况
k = k % nums.length;
if (k == 0) {
return;
}
// 通过k次循环,每次将数组整体向右移动一位
for (int i = 0; i < k; i++) {
// 保存最后一个元素
int lastElement = nums[nums.length - 1];
// 从后往前移动元素(避免覆盖问题)
for (int j = nums.length - 1; j > 0; j--) {
nums[j] = nums[j - 1];
}
// 将最后一个元素放到第一位
nums[0] = lastElement;
}
}
这里的思路我们通过for 循环交换我们相邻的元素的位置 j和 j-1的位置还有我们外层有一个循环就是我们的k是多少我们就循环转几次 这种写法看着代码比较容易理解 但是我们的时间复杂度很高是o(n平方) 所以这种办法不是最优解 我们还要注意的就是我们最后一个元素和第一个元素 交换位置我们要注意数组越界的问题
单元测试
public static void main(String[] args) {
Leetcode6 leetcode6 = new Leetcode6();
// 测试用例1:正常数组旋转
System.out.println("=== 测试用例1:正常数组旋转 ===");
int[] nums1 = {1, 2, 3, 4, 5, 6, 7};
int k1 = 3;
System.out.print("原数组: ");
printArray(nums1);
leetcode6.test(nums1, k1);
System.out.print("旋转后: ");
printArray(nums1);
System.out.println("期望结果: [5, 6, 7, 1, 2, 3, 4]");
System.out.println();
// 测试用例2:边界情况测试
System.out.println("=== 测试用例2:边界情况测试 ===");
// 空数组测试
System.out.println("空数组测试:");
int[] nullArray = null;
System.out.println("执行前: null");
leetcode6.test(nullArray, 3);
System.out.println("执行后: " + (nullArray == null ? "null" : "not null"));
System.out.println();
// 单元素数组测试
System.out.println("单元素数组测试:");
int[] singleElement = {1};
System.out.print("执行前: ");
printArray(singleElement);
leetcode6.test(singleElement, 5);
System.out.print("执行后: ");
printArray(singleElement);
System.out.println();
// k为0测试
System.out.println("k为0测试:");
int[] zeroKArray = {1, 2, 3};
System.out.print("执行前: ");
printArray(zeroKArray);
leetcode6.test(zeroKArray, 0);
System.out.print("执行后: ");
printArray(zeroKArray);
System.out.println();
// 测试用例3:k大于数组长度
System.out.println("=== 测试用例3:k大于数组长度 ===");
int[] nums3 = {1, 2, 3, 4, 5};
int k3 = 7; // 7 % 5 = 2
System.out.print("原数组: ");
printArray(nums3);
leetcode6.test(nums3, k3);
System.out.print("旋转后: ");
printArray(nums3);
System.out.println("期望结果: [4, 5, 1, 2, 3]");
}
// 辅助方法:打印数组
private static void printArray(int[] arr) {
if (arr == null) {
System.out.println("null");
return;
}
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if (i < arr.length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
第二种解题方法
public void test2(int[] nums, int k){
// 添加边界检查
if (nums == null || nums.length <= 1 || k <= 0) {
return;
}
// 处理k大于数组长度的情况
k = k % nums.length;
if (k == 0) {
return;
}
// 使用三次反转法实现数组旋转,时间复杂度O(n),空间复杂度O(1)
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 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--;
}
}
第二种方法我们其实思路也是互相交互元素但是我们 分为3端 第一个后我们最后一个元素交互 然后第一个元素到k-1 然后k 到最后一个元素 通过我们的reverse 方法3次反转实现数组的旋转,时间复杂度O(n),空间复杂度O(1) 对比第一种解法我们的时间复杂度下降很多,也更合理了。
-
单元测试
public static void main(String[] args) {
Leetcode6 leetcode6 = new Leetcode6();
// 测试用例1:正常数组旋转
System.out.println("=== 测试用例1:正常数组旋转 ===");
int[] nums1 = {1, 2, 3, 4, 5, 6, 7};
int k1 = 3;
System.out.print("原数组: ");
printArray(nums1);
leetcode6.test2(nums1, k1);
System.out.print("旋转后: ");
printArray(nums1);
System.out.println("期望结果: [5, 6, 7, 1, 2, 3, 4]");
System.out.println();
// 测试用例2:边界情况测试
System.out.println("=== 测试用例2:边界情况测试 ===");
// 空数组测试
System.out.println("空数组测试:");
int[] nullArray = null;
System.out.println("执行前: null");
leetcode6.test2(nullArray, 3);
System.out.println("执行后: " + (nullArray == null ? "null" : "not null"));
System.out.println();
// 单元素数组测试
System.out.println("单元素数组测试:");
int[] singleElement = {1};
System.out.print("执行前: ");
printArray(singleElement);
leetcode6.test2(singleElement, 5);
System.out.print("执行后: ");
printArray(singleElement);
System.out.println();
// k为0测试
System.out.println("k为0测试:");
int[] zeroKArray = {1, 2, 3};
System.out.print("执行前: ");
printArray(zeroKArray);
leetcode6.test2(zeroKArray, 0);
System.out.print("执行后: ");
printArray(zeroKArray);
System.out.println();
// 测试用例3:k大于数组长度
System.out.println("=== 测试用例3:k大于数组长度 ===");
int[] nums3 = {1, 2, 3, 4, 5};
int k3 = 7; // 7 % 5 = 2
System.out.print("原数组: ");
printArray(nums3);
leetcode6.test2(nums3, k3);
System.out.print("旋转后: ");
printArray(nums3);
System.out.println("期望结果: [4, 5, 1, 2, 3]");
}
// 辅助方法:打印数组
private static void printArray(int[] arr) {
if (arr == null) {
System.out.println("null");
return;
}
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if (i < arr.length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}