壹 ❀ 引

今天来做一道同样简单,但是挺有趣的题,题目来自leetcode189. 旋转数组,题目描述如下:

给定一个数组,将数组中的元素向右移动 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) 的 原地 算法。

老规矩,在分析完题目后,我先来说说我的实现思路,再来解析优质的解答。

贰 ❀ 解题思路

其实也不用被题目吓到,说是旋转数组,其实就是给定一个k表示要将数组最后一位数转移到数组头部次数的操作,比如第二个例子,k为2,表示一共要进行两次操作:

第一次将数组最后一位也就是99移动到数组头部。此时数组变成了[99,-1,-100,3],接着第二次操作,这时候最后一位是3:

此时数组变成了[3,99,-1,-100]

由于k为2,只需要执行2次,所以旋转数组完成,思路已经很清晰了,我们来实现它:

/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
// 如果数组只有一位或为空不用做任何操作
if(nums.length<=1){
return;
};
while(k>0){
//每次取最后一位,并加入到头部,由于splice返回的是数组,利用拓展运算符...还原成单个元素
nums.unshift(...nums.splice(-1,1));
k--;
};
};

哎,有同学可能就想到了,我何必一个个的转义,k为2,说到底就是把数组倒数两个元素整个搬到数组头部即可,然后我就开始写了如下代码:

/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function (nums, k) {
nums.length <= 1 ? nums : nums.push(...nums.splice(0, nums.length - k));
};

2020.8.12更新

经博客园用户Gary咖喱指出,对于splice第一参数为负数情况描述有误,特做修正。

注意,这里的splice我是正向剪切,原因是我发现splice的第一个参数为负数时,比如-1表示倒序最后一个开始,第二个参数不管是几,都只能剪一个:

[1,2,3].splice(-1,1); //[3]
[1,2,3].splice(-1,2); //[3]

当第一参数为负数时,表示倒序剪切,最后一个为-1,倒数第二个为-2,倒数第三个为-3,但裁剪顺序还是从左往右裁剪。

如上图,由于-1是最后一个元素,再往右没有其它元素,所以第二参数不管是1还是2,都只能裁剪一个,如果我们想裁剪多个,比如:

[1,2,3].splice(-3,3); //[1,2,3]

因为-3是第一个,从左到右剪切3个,这样就达到目的了。

最后需要补充的就是当第一参数为负数,且绝对值大于数组长度的情况,比如:

[1,2,3].splice(-4,3); //[1,2,3]

其实可以理解为裁剪起点在元素1(也就是索引-3)的左边,往右裁剪自然涵盖住了整个数组,所以本质还是对整个数组进行了裁剪。

前面的思路是把尾部剪切了拼到头部,我们何不反过来,比如[3,99,-1,-100]我们剪3,99push到-100后面呢,所以这才有了nums.length - k表示前面我们应该剪切的个数。

很遗憾,这段代码看似可以,但提交挂掉了,原因是这段代码只满足数组length大于k的情况,比如数组为[1,2],k为3,正确答案是交换3次变成[2,1]

而此时nums.length - k为-1,splice一大特点就是第二参数为0或者负数,表示一个不剪切,所以不符合。

此时,博客园用户love编程的小可爱想到了%求余,我立马灵光闪现改进了代码:

/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function (nums, k) {
nums.length <= 1 ? nums : nums.push(...nums.splice(0, nums.length - (k % nums.length)));
};

唯一区别只是在于nums.length - (k % nums.length),什么意思呢?

比如有数组[1,2,3,4],k为4,旋转4次后你会发现结果和最初的样子一模一样。而且只要k为数组长度的整数倍都会造成这种情况。

所以比如k为5,其实可以看成4+1次,我们只用旋转一次即可了,而%求余正好能达到这个效果:

8%4 //0
9%4 //1
3%4 //3
2%4 //2

所以用k%length算出我们真正要旋转数组的次数即可,一行代码搞定。

题目要求最少三种方法解答问题,但我没能想出其它做法,这里再补充其它不错的做法。

引用leetcode用户秦时明月的一个不错的做法,不用splice,直接利用pop即可:

/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums,k) {
for(var i = 0;i<k;i++){
nums.unshift(nums.pop());
};
};

这个就比我第一种实现要优雅的多了。

然后我在看leetcode用户的做法时,splice发挥到了极致:

/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
nums.splice(0,0,...nums.splice(nums.length-k))
};

这代代码执行是这样,比如数组[1,2,3,4],假设k为3,先执行...nums.splice(nums.length-k),得到了2,3,4。此时数组变成了[1]

接着执行前面的nums.splice(0,0,2,3,4),表示从0位前面插入元素2,3,4于是变成了[2,3,4,1]

那么关于本题就说到这了。

JS leetcode 旋转数组 题解分析的更多相关文章

  1. leetcode旋转数组查找 二分查找的变形

    http://blog.csdn.net/pickless/article/details/9191075 Suppose a sorted array is rotated at some pivo ...

  2. (LeetCode)旋转数组

    原体描写叙述例如以下: Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3 ...

  3. [LeetCode] Rotate Array 旋转数组

    Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array  ...

  4. LeetCode 189. Rotate Array (旋转数组)

    Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array  ...

  5. 【Leetcode】【简单】【189. 旋转数组】【JavaScript】

    189. 旋转数组 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3输出: [5,6,7,1,2,3,4]解释 ...

  6. LeetCode初级算法--数组02:旋转数组

    LeetCode初级算法--数组02:旋转数组 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ ...

  7. [LeetCode] 189. Rotate Array 旋转数组

    Given an array, rotate the array to the right by k steps, where k is non-negative. Example 1: Input: ...

  8. 前端与算法 leetcode 189. 旋转数组

    目录 # 前端与算法 leetcode 189. 旋转数组 题目描述 概要 提示 解析 算法 # 前端与算法 leetcode 189. 旋转数组 题目描述 189. 旋转数组 概要 把他当做一到简单 ...

  9. LeetCode 189. 旋转数组(Rotate Array)

    189. 旋转数组 LeetCode189. Rotate Array 题目描述 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: [1,2,3,4,5,6, ...

  10. 用js刷剑指offer(旋转数组的最小数字)

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个 ...

随机推荐

  1. ES 分词器简单应用

    本文为博主原创,未经允许不得转载: 1. ES 分词器 1.1 elasticsearch 默认分词器: standard standard 分词器会将每个英文单词及每个汉字进行单独拆分进行索引 使用 ...

  2. 一文搞清楚Java中的方法、常量、变量、参数

    写在开头 在上一篇文章:一文搞清楚Java中的包.类.接口 中我们讲了Java中的包.类和接口,今天继续将剩下的方法.常量.变量以及参数梳理完. Java中的变量与常量 在JVM的运转中,承载的是数据 ...

  3. 【BUS】动画图解嵌入式常见的通讯协议:SPI、I²C、UART、红外 ......

    SPI传输 SPI数据传输 SPI数据传输 SPI时序信号 I2C传输 2C总线寻址 UART传输 PC-UART-MCU RS-232电平转换 红外控制 红外通信 红外信号接收.放大.整形 红外控制 ...

  4. [转帖]【最佳实践】prometheus 监控 sql server (使用sql_exporter)

    https://www.cnblogs.com/gered/p/13535212.html 目录 [0]核心参考 [简述] [1]安装配置 sql_exporter [1.1]下载解压 sql_exp ...

  5. 监控服务器所有磁盘的inode使用情况

    监控服务器所有磁盘的inode使用情况 背景 因为前期数据库开启了审计 但是如果是 DB模式的话 $aud 表的冲突和使用太多了 所以专家建议将审计表放到OS 因为数据库的访问量特别高. 审计的信息又 ...

  6. [转帖]Docker容器日志查看与清理(亲测有效)

    1. 问题 docker容器日志导致主机磁盘空间满了.docker logs -f container_name噼里啪啦一大堆,很占用空间,不用的日志可以清理掉了. 2. 解决方法 2.1 找出Doc ...

  7. linux获取文件或者是进程精确时间的方法

    linux获取文件或者是进程精确时间的方法 背景 很多时候需要精确知道文件的具体时间. 也需要知道进程的开始的精确时间. 便于进行一些计算的处理. 其实linux里面有很多方式进行文件属性的查看. 这 ...

  8. [转帖]tidb4.0.4使用tiup扩容TiKV 节点

    https://blog.csdn.net/mchdba/article/details/108896766 环境:centos7.tidb4.0.4.tiup-v1.0.8 添加两个tikv节点   ...

  9. [转帖] Linux命令拾遗-入门篇

    https://www.cnblogs.com/codelogs/p/16060394.html 原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 之前出过很多和 ...

  10. Linux无头模式使用mat分析dump的方法

    摘要 mat可以很好的进行jvm的内存dump的分析. 但是大部分服务器是没有GUI界面的. 而且就算是有GUI界面也很难直接使用. 但是随着jvm堆区越来越大. WindowsPC机器已经很难进行分 ...