Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
菜鸟就要从第9题继续
一、题目描述:
给你一个数组,将数组中的元素向右轮转
k**个位置,其中k**是非负数。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ro… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
第一版:直观来想,在不限制原位替换的情况下,只要一个新的数组,按照规则进行轮转计算即可,通过i+k对n求余就可以求出新数组的值,然后循环替换。
环状替换的思路就是根据1个1个依次进行替换,若循环完一次则进行下一次循环,直至完成所有。这块有一个关键点就是要判断要走多少个环,求最大公约数,这里还用了递归。 这个如果我直接写,回写成换一个位置加一计数,没有找到最大公约的内在规律。
最后一个方法,数组翻转很有意思,当我们将数组的元素向右移动k次后,尾部k%n个元素会移动至数组头部,其余元素向后移动k%n个位置。这里先将所有元素翻转,这样尾部的 k%n个元素就被移至数组头部,然后我们再翻转 [0, k%n-1]区间的元素和 [k%n,n−1] 区间的元素即能得到最后的答案。 这个如果我来写,可能不会单独拿出一个函数来做数组传入start和end来做翻转,而回直接输入数组最后再拼接,虽然思路清晰但不够通用。
三、AC 代码:
1、第一版
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
const n=nums.length
let newNums =new Array()
for (let i = 0; i < n; ++i) {
newNums[(i + k) % n] = nums[i];
}
for (let y = 0; y < n; ++y) {
nums[y] = newNums[y];
}
};
2、环状替换
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
const gcd = (x, y) => y ? gcd(y, x % y) : x;
var rotate = function(nums, k) {
const n = nums.length;
k = k % n;
let count = gcd(k, n);
for (let start = 0; start < count; ++start) {
let current = start;
let prev = nums[start];
do {
const next = (current + k) % n;
const temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
} while (start !== current);
}
};
3、数组翻转
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
const reverse = (nums, start, end) => {
while (start < end) {
const temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start += 1;
end -= 1;
}
}
var rotate = function(nums, k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
};