持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
题目(Rotate Array)
链接:https://leetcode-cn.com/problems/rotate-array
解决数:2600
通过率:44.4%
标签:数组 数学 双指针
相关公司:microsoft amazon bytedance
给你一个数组,将数组中的元素向右轮转 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
进阶:
- 尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
- 你可以使用空间复杂度为
O(1)的 原地 算法解决这个问题吗?
思路
一 API
旋转数组 即 将数组后k位放到前面。对于JS将复杂度高逻辑由底层处理,实际性能可能更优
var rotate = function(nums, k) {
nums.splice(0, 0, ...nums.splice(-(k %= nums.length), k))
};
二 补位
倒序遍历,数组增加k位整体后移。指针到k后,把[n, n + k]位移回[0, k]。截断到n
取余:当k>数组长度,测试用例[1, 2] 3等同于[1, 2] 1 3 / 2取余即可
var rotate = function(nums, k) {
let n = i = nums.length
if ((k %= n) === 0) return
while (i--) {
nums[i + k] = nums[i]
if (i <= k) nums[i] = nums[n + i]
}
nums.length = n
};
不取余:JS数组长度最大不应超过安全整数。当k过大时,不取余存在溢出风险
var rotate = function(nums, k) {
let n = i = nums.length
while (i--) nums[i + k] = nums[i]
for (i = k; i--;) nums[i] = nums[n + i]
nums.length = n
};
三 翻转
原数组翻转 → [0, k)翻转 → [k, 数组长度)翻转,即解
双指针
var rotate = function(nums, k) {
const n = nums.length
if ((k %= n) === 0) return
reverse(nums, 0, n - 1)
reverse(nums, 0, k - 1)
reverse(nums, k, n - 1)
};
const reverse = (nums, l, r, t) => {
while (l < r) {
t = nums[l]
nums[l++] = nums[r]
nums[r--] = t
}
}
reverse
var rotate = function(nums, k) {
nums.reverse().slice(0, k %= nums.length).reverse().concat(nums.slice(k).reverse()).forEach((v, i) => nums[i] = v)
};
四 数组
i旋转k位后的指针是(i + k) % 数组长度,辅助数组存旋转后结果,再赋值回原数组
var rotate = function(nums, k) {
let n = nums.length, i = -1, a = new Int32Array(n)
while (++i < n) a[(i + k) % n] = nums[i]
while (i--) nums[i] = a[i]
};
五 环状
来自《力扣官方题解》 最小公约数
var rotate = function(nums, k) {
let n = nums.length, max = gcd(n, k), i = -1
while (++i < max) {
let prev = nums[i], j = i
while (i !== (j = (j + k) % n)) {
const t = nums[j]
nums[j] = prev
prev = t
}
nums[i] = prev
}
};
const gcd = (n, k) => k ? gcd(k, n % k) : n
计数:遍历过的值 < 数组长度
var rotate = function(nums, k) {
let n = nums.length, visited = -1, i = 0
if ((k %= n) === 0) return
while (++visited < n) {
let prev = nums[i], j = i
while (i !== (j = (j + k) % n)) {
const t = nums[j]
nums[j] = prev
prev = t
visited++
}
nums[i++] = prev
}
};