# 189 旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: [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:

输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释: 
向右旋转 1: [99,-1,-100,3]
向右旋转 2: [3,99,-1,-100]

说明:

尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。 要求使用空间复杂度为 O(1) 的 原地 算法。

# 题解

  1. 使用 splice 计算出要移动的个数,然后使用 unshift 一次性移动过去。

TIP

执行用时:84 ms, 在所有 JavaScript 提交中击败了 88.40% 的用户

内存消耗:38.9 MB, 在所有 JavaScript 提交中击败了 30.44% 的用户

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    const {length: l} = nums
    /**
     * k % l 获取真正的移动个数
     * l - 移动个数 为 splice 就是要移动的内容
     * 使用 unshift 一次性移动到数组的开头
    */
    nums.unshift(...nums.splice(l - (k % l)))
    return nums
};
  • 时间复杂度: O(1),使用 splice 移动数组,使用 unshift 添加,所以不涉及到遍历。
  • 空间复杂度:O(1),因为移动的是原数组,所以空间复杂度为 O(1)
  • 最好情况:k 为 0 或者数组的长度,那么要移动的内容比较少或者不移动。
  • 最坏情况:k 为 数组的长度-1,那么要移动的内容比较多。
  1. 暴力解法,使用 while循环,每次删除数组的最后一个,同时添加到数组的开头。

TIP

执行用时:124 ms, 在所有 JavaScript 提交中击败了 35.94% 的用户

内存消耗:38.7 MB, 在所有 JavaScript 提交中击败了 59.23% 的用户

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    k = k % nums.length
        // 每次 k 递减,当为 0 时则退出循环
    while (k--) {
        // 删除数组最后一个元素
        let num = nums.pop()
        // 添加至数组的开头,因为添加至数组的开头,所以数组后面的内容依次需要移位,虽然不需要我们手动操作,但还是耗性能。
        nums.unshift(num)
    }
    return nums
};
  • 时间复杂度:O(n),使用了 while循环,n 即 k 的值,经过处理后,最大为数组的长度,最小为 1。
  • 空间复杂度:O(1),使用常数级别的变量 num 进行保存。
  • 最好情况: k 为 0 或者数组的长度。
  • 最坏情况: k 为数组的长度 - 1。
最后更新时间: 9/4/2020, 10:41:26 PM