数组「4」旋转数组 | 刷题打卡

350 阅读2分钟

前言

最近身体很差,浑身疼,脱发严重,长痘痘,唉。。。

要认真学习,好好找工作啊,每天的任务不能怠慢。

今日题目

leecode189: leecode189.旋转数组

给定一个数组,将数组中的元素向右移动 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]

解题思路

思路一:使用额外的数组

这是看到题目第一个想到的方法,也是相对简单的方法。

创建一个新数组,遍历原数组,将数组元素放到指定的位置即可

var rotate = function(nums, k) {
    const length = nums.length
    const result = []
    for(let i = 0; i < length; i++) {
        result[(k + i) % length] = nums[i]
    }
    for(let i = 0; i < length; i++) {
      nums[i] = result[i]
    }
    return nums
};

由于创建了新的数组,并等于原数组长度,所以空间复杂度是O(n)

遍历了两次数组,时间复杂度O(n)

思路二: 数组翻转

将数组向右移动k位,得到的数组k % length的尾部元素被移动到头部,剩下的元素向后移动

将原数组全部翻转

再将前k个元素翻转

再将后length-k元素翻转

经过三次翻转后得到目标数组

var rotate = function(nums, k) {
    k %= nums.length;
    reverse(nums, 0, nums.length);
    reverse(nums, 0, k);
    reverse(nums, k, nums.length);
};
function reverse(nums, begin, end) {
    var left = begin;
    var right = end - 1;
    while(left < right) {
        var temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
        left += 1;
        right -= 1;
    }
}
思路三: 循环移位算法

对于一个长度为n的数组,整体移动k位

如果n和k的最大公约数是1, 代表1次循环就可以交换完成,n= 7 k=3 最大公约数为1

如果n和k的最大公约数大于1, 需要最大公约数次循环可以交换完成,n=6 k=4 最大公约数是2

如下是k=3, n=7的情况,1次循环就结束 如下是k=4, n=6的情况,2次循环结束

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);
    }
}

总结

本题使用了三种算法解决问题,循环移位方法数组翻转方法在字符串的题目中也经常遇到,理解花了一些时间,但是搞懂了对其他题目是有很大帮助的。

这次题解写了大半天的时间, 要滚去干活咯。。。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情