壹 ❀ 引

又到了每日一道算法题的环节,今天做的题同样非常简单,题目来源leetcode27. 移除元素,题目描述如下:

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。

同样,我先说说我的解题思路,再分享更优的做法。

贰 ❀ 解题思路

即便是未了解过算法的同学我想应该都能轻易做出,题目要求很明了,给定一个数组与一个目标值,删除数组中与目标值相同的元素,最终返回操作完的数组长度。

这里我首先想到的肯定是直接使用splice删除符合条件的元素,直接贴代码:

/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function (nums, val) {
var i = 0,
len = nums.length;
for (; i < len; i++) {
// 如果当前项与目标值相同,则删除这一样
if (nums[i] === val) {
nums.splice(i, 1);
i--;
};
};
return nums.length;
};

思路很简单,这里我们还是简单复习一下splice方法,splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。它接受三个参数:

arrayObject.splice(index,howmany,item1,.....,itemX)

其中index表示你要操作的起点,代表数组索引;howmany表示操作的个数,比如我要删除2个,还是3个。而item1,.....,itemX表示删除之后你希望加入的新元素。

需要注意的是splice方法会直接改变原数组,并返回被删除的元素数组。

let arr = [0,1,2,3];
let arr_ = arr.splice(0,2,4,5);
console.log(arr,arr_);// [4,5,2,3] [0,1]

这段代码表示,从arr索引0处删除2个元素,也就是0,1,删除后再加入4,5,所以修改后的arr为[4,5,2,3],返回的删除元素组成新的数组[0,1]

为什么里面有个i--呢,这是因为splice操作会修改原数组,让我们删除一项后,数组的length已经发生了变化,还按照原本i++遍历,会造成遍历跳过一项的问题,i--的目的就是为了重置i。

关于删除数组某项后要i--的思路,我保持了2年,直到今天遇到这道算法题,我才被改变,来看一个更棒的写法:

/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) {
if(nums.length===0){
return nums.length
};
for(let i = 0;i<nums.length;){
if(val === nums[i]){
nums.splice(i,1)
}else{
i++
};
};
return nums.length
};

为了方便理解,举个例子,比如我们要删除数组[2,1,2]中的所有2,按照我前面的写法。

第一次遍历遇到2,i此时为0,删除后数组变成[1,2],i自增变成1,很明显1没判断被跳过了,所以才需要i--,让i变成-1,于是第二次遍历i++又变成了0,这样就不会跳过1了。

有没有觉得i--i++非常多余呢,上面优化的写法就是解决了这个问题,如果进行了删除操作,我们让当前的i不自增不就好了,只有不满足是才自增比较下一位。直到这段代码,改变了我2年多以来的的编程思路...

那么到这里就结束了吗?并没有,题目描述结尾有这样话,剩下的元素可为任意顺序,你不需要考虑数组中超出新长度后面的元素。

说实话我都不明白它想表达什么,直到我看了别人针对这句话想出的解答思路才明白是怎么回事。比如数组[2,1,3,2]要删除2,你可以把数组变成[1,3,2,2]都算符合答案,意思就是我得到了数组[1,3],只是这个数组超出了长度多了两个2,题目也说了不考虑超出,那么针对这个思路再给出一个实现,实现灵感来自于leetcode用户灵魂画手

/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) {
let ans = nums.length;
for (let i = 0; i < ans;) {
// 只要当前元素与val相同,就与数组后面交换
if (nums[i] == val) {
[nums[i], nums[ans - 1]] = [nums[ans - 1], nums[i]];
// 注意这里递减有两个目的
// 1.第一是保证每次交换都会往前走一位,不然一直交换最后一位了
// 2.第二是模拟删除掉val后剩余的元素个数
ans--;
} else {
i++;
};
};
return ans;
};

这个思路注释其实已经说的很明白了,符合条件的元素我们把它往数组最后面丢,用个例子来模拟一下,比如数组[3,2,1,3],我们要求去掉3的长度。

第一次遍历,i为0,nums[0]与3比较由于符合,那么当前 i 的元素就和数组最后一位互换,此时数组变成了[3,2,1,3]

注意,由于你不知道换过来的最后一位是否符合条件,所以此时 i 并不能自增,而是让ans递减,作用注释也说了。

于是仍然是nums[0]和3比较,又符合条件,这时候就不是和最后一位互换,由于ans递减,所以是倒数第二位,于是数组变成了[1,2,3,3],注意此时ans又得递减,i不变。

继续遍历,还是nums[0]与3比较,不符合,所以i自增,于是nums[1]又与目标值比较,不符合条件,最终跳出了循环。

由于有2个符合条件的元素,所以ans本质上等于原数组长度4-2=2,最终返回了2。

老实说,不看这个答案,我确实想不到这个题目描述是这个意思....当然这个实现思路确实很巧妙,也感叹大佬的思路也是够清晰。

那么关于此题就分析到这了。

JS leetcode 移除元素 题解分析的更多相关文章

  1. LeetCode移除元素

    LeetCode 移除元素 题目描述 给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不需要使用额外的数组空间,你必须仅使用 O(1) ...

  2. LeetCode~移除元素(简单)

    移除元素(简单) 1. 题目描述 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使 ...

  3. 【数组】leetcode——移除元素

    编号:27. 移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 ...

  4. leetcode 移除元素

    给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...

  5. 前端与算法 leetcode 27.移除元素

    目录 # 前端与算法 leetcode 27.移除元素 题目描述 概要 提示 解析 算法 @(目录) # 前端与算法 leetcode 27.移除元素 题目描述 27.移除元素 概要 题目本身其实挺简 ...

  6. 【JavaScript】Leetcode每日一题-移除元素

    [JavaScript]Leetcode每日一题-移除元素 [题目描述] 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用 ...

  7. 分析轮子(八)- List.java 各种遍历方式及遍历时移除元素的方法

    注:玩的是JDK1.7版本 1:先尝栗子,再分析,代码简单,注释清晰,可自玩一下 /** * @description:测试集合遍历和移除元素的方式 * @author:godtrue * @crea ...

  8. JS中对数组元素进行增删改移

    在js中对数组元素进行增删改移,简单总结了一下方法: 方法 说明 实例 push( ); 在原来数组中的元素最后面添加元素 arr.push("再见58"); unshift( ) ...

  9. Java实现 LeetCode 27 移除元素

    27. 移除元素 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额 ...

  10. 每日一道 LeetCode (8):删除排序数组中的重复项和移除元素

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

随机推荐

  1. Android Emulator 画面闪烁

    Android 虚拟机经常会出现画面闪烁,可以通过修改设置解决. 打开虚拟机之后,点击 "..." 按钮.按照下图改为 "D3D11",冷重启虚拟机就好了.

  2. 【转】嵌入式C语言代码优化方案

    来源:嵌入式C语言代码优化方案(深度好文,建议花时间研读并收藏) (qq.com) 1.选择合适的算法和数据结构 选择一种合适的数据结构很重要,如果在一堆随机存放的数中使用了大量的插入和删除指令,那使 ...

  3. [转帖]Shell编程之正则表达式与文本处理器(grep、sort、uniq、tr、cut)

    目录 正则表达式概念 正则表达式的作用 元字符 grep命令在文本中查找指定的字符串 sort命令排序 uniq命令快捷去重 tr命令替换.压缩和删除 cut命令快速裁剪命令 expr substr ...

  4. [转帖]CentOS8时间同步服务

    时间同步服务 CentOS7之前的版本用的是ntpdate服务,之后用的是chrony服务 默认是安装的了 查看版本 [root@centos8 ~]#rpm -qi chrony Name : ch ...

  5. [转帖]Flink完全分布式集群安装

    https://zhuanlan.zhihu.com/p/131592261 Flink支持完全分布式模式,这时它由一个master节点和多个worker节点构成.在本节,我们将搭建一个如下的三个节点 ...

  6. [转帖]Linux中find命令使用示例

    https://zhuanlan.zhihu.com/p/99170116 Linux查找命令是类Unix操作系统中最重要且最常用的命令行实用程序之一. 查找命令可以根据你设定的参数匹配的文件指定的条 ...

  7. [转帖]传输层安全协议真(TLS)的安全吗?

    https://zhuanlan.zhihu.com/p/305161227 随着数字通信,计算机网络,公钥密码体制等技术的迅速发展,安全网络通信已经成为了人们的日常需求.TLS 作为目前被广泛应用的 ...

  8. [转帖]SHELL—— awk两个特殊模式(BEGIN 和 END)及awk高级应用(条件判断、循环)

    一.Awk 的两个特殊模式 BEGIN 和 END,BEGIN 被放置在没有读取任何数据之前,而 END 被放置在所有的数据读取完成以后执行 体现如下: BEGIN{}: 读入第一行文本之前执行的语句 ...

  9. Find 查找并且展示最近24小时内创建的文件信息

    1. 命令为: find /gscloud/tools/patchinstall/patchfiles/ -maxdepth 1 -mtime 1 |cut -c40- >/deploy/pat ...

  10. chrome谷歌浏览器多开(独立环境 独立cookie)

    复制下面代码(路径) "C:\Program Files\Google\Chrome\Application\chrome.exe" --user-data-dir="D ...