LeetCode189-轮转数组 | 算法练习系列

303 阅读2分钟

这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

前言

继续来一道数组处理的算法题,轮转数组,这个题目个人感觉还是有坑的,一不小心就掉坑里了,下面看看我到底经历了什么

题目描述

给你一个数组,将数组中的元素向右轮转 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]

解题思路

  • 这一题乍一看很简单,但一般看起来简单的东西往往不会那么简单,当看到这道题,我便开始了一顿操作,我首先想到的就从新声明一个数组,首先把nums赋值给它,然后再根据k取nums的后几个数据插入新数组,然后再根据nums的长度进行切割,美滋滋,得到了结果,看代码
var rotate = function (nums, k) {
      const n = nums.length
      let result = [...nums]
      for (let i = 0; i < k; i++) {
        result.unshift(nums[n - 1 - i])
      }
      result = result.slice(0, n)
      return result
    };
复制代码
  • 但是万万没想到了,我得到了错误的结果

错误.png

  • 我人傻了,我在vs code中明明是正确的,一顿烦躁,找了好久问题,原来是没理解题的意思。emmm....

emmm.PNG

  • 真是够无语的,原来不需要返回值,需要改变的是原数组,也就是nums,于是我又开始操作
var rotate = function(nums, k) {
     k=k%nums.length
     const n = nums.length
      let result = [...nums]
      for (let i = 0; i < k; i++) {
        result.unshift(nums[n - 1 - i])
      }
      for(let i=0;i<n;i++){
          nums[i] = result[i]
      }
};
复制代码
  • 以为美滋滋了,可没想到竟然超时了。。。。在网上搜了一下发现unshift的效率极低,比push操作效率低差不多100倍(如下图),那只能再改代码了,只能声明一个新数组,一个个进行轮转,最后将轮转之后的新数组再赋值给nums,代码如下

性能测试.PNG

var rotate = function(nums, k) {
    const n = nums.length;
    const newArr = new Array(n);
    for (let i = 0; i < n; ++i) {
    //这里i+k%n的操作是k有可能比n还大,所以要这么处理
        newArr[(i + k) % n] = nums[i];
    }
    for (let i = 0; i < n; ++i) {
        nums[i] = newArr[i];
    }
};

复制代码

总结

终于通过了。。。原本以为这题是非常简单的一道题目,没想到一波三折,但总算有些收获,下次遇到问题一定要认真看题,也知道了unshift的效率极低,特别是处理大数组的时候,能不用还是不要用,继续努力,gogogo!!!