LeetCode算法练习(三) 旋转数组

前言:

最近由于工作较忙,练习的频率有点低了,以后尽量保持两到三天练习一道的频率和效率。

那么开始这一次算法练习。

题目描述:

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

示例 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) 的 原地 算法。

解题思路:

看到题目我首先注意到了要使用空间复杂度为O(1)的原地算法,那么我们就不能再创建新的数组来作为辅助,所以我想到的是利用元素替换的方法,但是想了很久没有成功解决,所以就想先借助额外的数组空间来解决(虽然是不满足题意的)。

方案1(不满足题意):

    let length=array.length;
    let realK=k%length;
    let index=length-realK;
    for(let i=0;i<length;i++){
        if(index<length){
            array.push(array[index]);
        }else {
            array.push(array[index-length])
        }
        index++;
    }
    array.splice(0,length);
    console.log(array);

这种方法是不满足题意的,因为使用了额外的数组空间。不过也讲一下解题思路,首先我们假设数组平移之后是下面这样的。

//原数组
[1,2,3,4,5]
//平移后的数组k=2
[4,5,1,2,3]
//我们发现数组平移后k指针之后的元素,我们把数组从k开始依次放入原数组,得到一个新数组
[1,2,3,4,5,4,5,1,2,3]
//最后截取原数组长度数组得到答案
[4,5,1,2,3]

上面的思路是很容易理解的,但是是不满足题意的,所以我继续想新的解决方案,我想到了将这个问题分解来解决,首先我们实现将数组移动一位的算法,那么之后循环k就可以解决,所以解决方案二如下。

方案二:

扫描二维码关注公众号,回复: 10179645 查看本文章
//缓存被替换的元素
let buffer=null;
//计算真实的k值
k=k%nums.length;
//移动k位
while (k>0){
    /*移动一位的算法*/
    for(let i=0;i<nums.length;i++){
        //指针越界之后的处理 
        if(i+1>=nums.length){
            let index=i+1-nums.length;
            nums[index]=buffer;
        }else{
            //首次遍历时buffer为null  
            if(buffer==null)
                //先保存要替换的元素的值
                buffer=nums[i+1];
                nums[i+1]=nums[i];
            }else{
                //for局部变量保存要替换的元素
                let b=nums[i+1];
                //给元素赋值上一次循环缓存的值
                nums[i+1]=buffer;
               //函数全局变量保存要替换的元素
                buffer=b;
            }
        }
    }
    k--;
}

这种方法可以说满足了题意,但是执行时间十分长,到该500-600ms,因为会循环执行很多次。所以我们提交答案之后就不厚道的去看了别人的答案=。=。

看到一个这样的解法:

方案三:

let length=array.length;
    let realK=k%length;
    for(let i=0;i<realK;i++){
      let num=nums.pop();
      nums.unshift(num);
    }
    console.log(nums);

代码逻辑很清晰,就是讲数组的最后一个元素pop出来,再使用unshift插入到数组的最前面即可 。

实际上我的第一种方案已经接近这个答案了,但是因为我不熟悉数组的api,pop、unshift、splice等,所以我都不知道js数组可以在数组的最前面(unshift)或者指定位置(使用splice)插入元素。

总结:

首先我感觉我还是不能把锅甩给不了解js数组的api,主要原因还是解题思路有问题。

如果我首先想到这个平移问题的本质是将最后一个元素取出,放到数组的前端,依次类推,那么我一定会去想办法找数组插入的方法,即使不知道unshift方法,使用我已知的splice方法也可以实现。

其次,我认为自己对数据结构的学习或者说理解不够,我认为是可以想成队列的数据结构的问题,如果一开始把这个数组结构想成是一个队列,平移操作想成是出队列再入队列即可解决这个问题。

综上所述,总结两点

1、复杂问题(虽然方法对了的话并不复杂=。=),学会将问题分解为单个简单操作;

2、要去复习一下数据结构的知识了!

发布了49 篇原创文章 · 获赞 19 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_33718648/article/details/97363398