LeetCode 27. 移除元素(JavaScript 简单)

2023-09-14 14:21:27

1. 题目

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

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

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

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度5,并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

提示:

  • 0 <= nums.length <= 100
  • 0 <= nums[i] <= 50
  • 0 <= val <= 100

2. 思路及代码

2.1 原思路和代码

利用双指针,一个指针p1指向要被替代的位置(此位置的值为 val),另一指针p2指向非val值nums[p2]。让 p2 指向的值替换掉 p1 位置上的原值。

注意点:

  • p2 要保持在 p1 之后
  • 由于 JavaScript 的数组不存在越界,要时常注意判断 p1 和 p2 是否越界了
  • 另外最终返回数组的长度,所以要搞清楚返回的边界是 p1 还是 p1-1
/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
    let p1=0, p2=0; //p1指向当前可能要被替换的位置,p2用遍历数组找到应该存下来的值
    n = nums.length
    while(p2<n && p1<n){
        while(p1<n && nums[p1]!=val){
            p1++; //找到当前值为 val 的位置 p1
        } 
        for(p2=p1+1; nums[p2]==val; p2++); //找到当前值不为 val 的值 nums[p2]
        if(p2>=n || p1>=n) break;
        nums[p1] = nums[p2];
        nums[p2] = val;
        p1++;
        p2++;
    }
    return p1;
};

2.2 反思和升级代码

  • 判断+移动 是两次计算,如果直接 移动 可以解决的,额外再判断一次浪费时间。所以可以不需要判断 p2 指向的值是不是 val。如果 p2 指向的值是 val,直接复制过来,只要 当 p1 指向的值不是 val 时 p1 才动即可。
  • 如果 p1 从数组起点开始,p2 从数组末尾开始,循环直到 p1===p2,这样总共循环只有 n(数组长度) 次。
  • 将 p2 位置上的值复制到 p1 位置上时注意。如果保证 p2 当前指向的值已经被复制到 p1 上(先挪动再复制),则最终 p1 和 p2 重合时,此时重合位置已经处理过,直接返回的p1就是数组长度
    • 如果是 p1 挪到 p2 上,p2指向的位置已被处理,则p1,p2此时指向的元素已经被复制到前面位置上,此时p1的下标就是数组长度;
    • 如果是 p2 挪到 p1 上,此时p2指向的位置已经被处理,p1和p2指向的位置就是上一步自己复制给自己的操作,nums[left]===val,当前元素是val,返回的p1除了自己当前的位置之前的所有位置都不是val,返回的 p1 就是数组长度。
  • p2 指向位置的值可能还没有被复制到 p1 上,当 p1 与 p2 重合时,还需要额外再讨论一次,当前 p1 指向的值是 val 时,返回的数组长度为 p1;当前 p1 指向的值不是 val 时,返回数组的长度应该是 p1+1。

双指针优化

left 指针(规定,如果需要两个指针且存在 p1<p2 的循环结束条件时命名为 left right)从数组索引 0 开始遍历,right 指针从数组索引 num.length()-1 开始遍历。当 nums[left] === val 时,将 nums[right - 1] 的值复制过来,right--;当 nums[left] !== val 时,left++。重复上句操作,直到 left===right 时循环终止,返回 left。

/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
    let left=0, right=nums.length; //left指向当前可能要被替换的位置,right用遍历数组找到应该存下来的值
    while(left < right){
        if(nums[left] == val) nums[left] = nums[--right];
        else left++;
    }
    return left
};

3. 总结经验

  1. 能不判断解决问题的,不要判断。获得最好的时间复杂度,不需要过细考虑。
  2. 在块作用域内起作用的变量,使用 let。

更多推荐

微信小程序部分知识点总结

简单描述下微信小程序的目录结构微信小程序的目录结构如下:app.js。微信小程序的主逻辑文件,用于描述小程序的基本逻辑和程序入口。app.json。微信小程序的公共设置文件,用于描述小程序的全局配置项,如页面路径、窗口样式等。app.wxss。微信小程序的公共样式表文件,用于描述小程序的全局样式,如字体、颜色等。pag

Java基于基于微信小程序的快递柜管理系统

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W+、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌文章目录第一章:简介第二章、***\*开发环境:\******后端:****前端:****数据库:**第三章系统设计3.3系统功能设计3.3.1用户注册

APP开发者如何运用积分墙广告,提升APP应用下载和用户留存?

“积分墙”移动广告通过在应用内展示各种积分任务,鼓励用户完成任务以获得积分奖励,从而增加应用的曝光度和下载量。一、什么是积分墙?积分墙是一种第三方移动广告平台。开发者可以在这类平台上发布任务(如下载安装App、注册、填表等),用户完成相应任务就可以获得积分或现金奖励,达到指定额度可以提现。二、积分墙包含哪几部分?(1)

springBoot整合minio

<minio.version>8.3.4</minio.version><!--其它&&数据源加密--><org.bouncycastle.bcprov-jdk15on.version>1.70</org.bouncycastle.bcprov-jdk15on.version><dependencies><depend

《向量数据库指南》——文心大模型+Milvus向量数据库搭建AI原生应用

亲爱的科技探险家们和代码魔法师们:未来的钟声已经敲响,预示着一场极度炫酷的虚拟现实游戏即将展开。从初期简单的智能识别,到设计师级别的图纸设计,生成式AI技术(GenerativeAI)以其独特理念和创新模式重塑了传统内容生产效率和交互模式,在无数领域展现着非凡的才华。在这场人工智能游戏中,高性能、高稳定的各类大模型的不

恩智浦i.MX8MM核心板在智能售货机产品中的应用方案-迅为电子

迅为i.MX8MM核心板在自动售货机产品中可以实现多种应用,提高自动售货机的功能和性能。以下是i.MX8MM核心板在自动售货机产品中的应用方案:支付和交易处理:i.MX8MM核心板可以用作自动售货机的支付和交易处理器,支持各种支付方式,如信用卡、手机支付、硬币和纸币识别,以提供便捷的购物体验。库存管理:核心板可用于实时

文举论金:黄金原油全面走势分析策略指导。

市场没有绝对,涨跌没有定势,所以,对市场行情的涨跌平衡判断就是你的制胜法宝。欲望!有句意大利谚语:让金钱成为我们忠心耿耿的仆人,否则,它就会成为一个专横跋扈的主人。空头,多头都能赚钱,唯有贪心不能赚。是你掌控欲望还是欲望掌控你?古人云:不积硅步无以至千里,不积小流无以成江海。希望这句话成为我们之间的共勉。自知!人贵自知

R语言绘图-3-Circular-barplot图

0.参考:https://r-graph-gallery.com/web-circular-barplot-with-R-and-ggplot2.html1.说明:利用ggplot绘制环状的条形图(circularbarplot),并且每个条带按照数值大小进行排列。2绘图代码:注意:绘图代码中的字体为“TimesNew

什么是单页面应用(SPA)?它们的优点和缺点是什么?

聚沙成塔·每天进步一点点⭐专栏简介⭐什么是单页面应用(SPA)?⭐SPA的优缺点是什么?⭐SPA中如何处理搜索引擎优化(SEO)?⭐什么是前端路由(Front-endrouting)在SPA中的作用是什么?⭐SPA中如何处理浏览器历史记录和页面刷新?⭐SPA通常使用哪些前端框架或库来简化开发?⭐写在最后⭐专栏简介前端入

WebGL笔记: 2D和WebGL坐标系对比和不同的画图方式, 程序对象通信,顶点着色器,片元着色器

WebGL坐标系canvas2d画布和webgl画布使用的坐标系都是二维直角坐标系,但它们坐标原点、y轴的坐标方向,坐标基底都不一样canvas2d坐标系的原点在左上角,x轴朝右,y轴朝下1个单位的宽就是一个像素的宽,1个单位的高就是一个像素的高,都是按像素来走webgl坐标系的原点在画布中心,x轴朝右,y轴朝上1个单

在线客服系统品牌排行榜

客服系统是针对企业和组织的客户服务领域开发和提供的一种信息化系统。它可以帮助企业更好地管理与顾客之间的沟通、反馈和服务等。随着互联网技术和人工智能技术的不断发展,市场上的客服系统产品越来越多,如何选择一款适合自己的产品成为众多企业和组织面临的问题。今天,我们为大家提供客户服务系统排行榜热门品牌榜,为大家在做选择时提供可

热文推荐