给你一个数组,将数组中的元素向右轮转 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]
题目要求提供多种解决方案,自己能想到的是方案1和方案2,并方案2调试很多次才能通过(不超时),方案3完全是看别人的解答分析后才提供出来的,但是方案3最巧妙耗时也最少。
import java.util.Arrays;
class Solution5 {
public void rotate(int[] nums, int k) {
int[] clone = Arrays.copyOf(nums, nums.length);
int n = nums.length;
k %= n;
for (int i = 0; i < nums.length; i++) {
nums[i] = clone[(i - k + n) % n];
}
System.out.println(Arrays.toString(nums));
}
public static void main(String[] args) {
Solution5 solution = new Solution5();
solution.rotate(new int[]{1, 2, 3, 4, 5, 6, 7}, 3);
}
}
这个方案重点就是不使用数组了,只需要部分变量就能完成整体的移动;这里通过图来分析:
得到下面的代码实现:
class Solution4 {
public void rotate(int[] nums, int k) {
k %= nums.length;
if (k == 0) {
return;
}
int count = 0;
for (int i = 0; i < k; i++) {
int index = i;
int start = index;
int value = nums[index];
while (true) {
if (count >= nums.length) {
break;
}
index += k;
if (index >= nums.length) {
index %= nums.length;
}
int temp = nums[index];
nums[index] = value;
value = temp;
count++;
if (start == index) {
break;
}
}
}
}
public static void main(String[] args) {
Solution4 solution = new Solution4();
solution.rotate(new int[]{1, 2, 3, 4, 5, 6}, 4);
solution.rotate(new int[]{1, 2, 3, 4, 5, 6, 7}, 3);
}
}
这个方案只需要3次操作,操作思路如下:
按照这个巧妙的思路代码如下:
class Solution {
public void rotate(int[] nums, int k) {
k %= nums.length;
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;
}
}
public static void main(String[] args) {
Solution solution = new Solution();
solution.rotate(new int[]{1, 2, 3, 4, 5, 6}, 4);
solution.rotate(new int[]{1, 2, 3, 4, 5, 6, 7}, 3);
}
}
这道题是一个要求有多种解决方案的问题,前2个方案我都能想到,但是在耗时方面都不是最好的;第三个方案,思路巧妙,代码实现简单,但我自己却没有想到。如果有更好的方案,欢迎回复。