「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」。
将指定的数组按某个数量级后移,你能想到集中算法实现呢?今天给大家展示下3种不同的解法,由浅入深的理解下。
题目描述
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
题目示例
题目解法
解法一:遍历拷贝法
在遍历数组过程,借助新的数组锚定数值,而后复制
/**
* 遍历拷贝法
*/
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
// 用于存储轮转后的数据
int[] newArray = new int[n];
for (int i = 0; i < n; ++i) {
// 锚定每个节点移动后的值
newArray[(i + k) % n] = nums[i];
}
// 系统函数拷贝
System.arraycopy(newArray, 0, nums, 0, n);
}
}
解法二:双指针动态规划
借助双指针标符,一个是指针,一个是移动值
/**
* 双指针动态规划
*/
class Solution {
public void rotate(int[] nums, int k) {
if (k < 1 || nums.length <= 1) {
return;
}
// 移位变更值
int hold = nums[0];
// 指针变动
int index = 0;
int length = nums.length;
boolean[] visited = new boolean[length];
for (int i = 0; i < length; i++) {
index = (index + k) % length;
if (visited[index]) {
index = (index + 1) % length;
hold = nums[(index + length - k) % length];
}
visited[index] = true;
int temp = nums[index];
nums[index] = hold;
hold = temp;
}
}
}
解法三:动态翻转数组
最为精妙的解法,先翻转全部,再反转前K个,后反转余下的
/**
* 动态翻转数组
*/
class Solution {
public void rotate(int[] nums, int k) {
int length = nums.length;
k = k % length;
// 全部翻转
reverseNum(nums, 0, length - 1);
// 反转前k个
reverseNum(nums, 0, k - 1);
// 翻转后几个
reverseNum(nums, k, length - 1);
}
public void reverseNum(int[] nums, int left, int right){
while (left < right) {
int temp = nums[left];
nums[left++] = nums[right];
nums[right--] = temp;
}
}
}
LeetCode原题链接:leetcode-cn.com/problems/ro…