移除元素 -- 力扣第27题 -- 暴力、双指针解法

题目

https://leetcode.cn/problems/remove-element/description/

给你一个数组 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。

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

思路

有的同学可能说了,多余的元素,删掉不就得了。

要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。

暴力解法

这个题目暴力的解法就是两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。

删除过程如下:

很明显暴力解法的时间复杂度是O(n^2),这道题目暴力解法在leetcode上是可以过的。

代码如下:(C++)

// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        for (int i = 0; i < size; i++) {
            if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
                for (int j = i + 1; j < size; j++) {
                    nums[j - 1] = nums[j];
                }
                i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
                size--; // 此时数组的大小-1
            }
        }
        return size;

    }
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

双指针法

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置

很多同学这道题目做的很懵,就是不理解 快慢指针究竟都是什么含义,所以一定要明确含义,后面的思路就更容易理解了。

删除过程如下:

很多同学不了解

双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。

后续都会一一介绍到,本题代码如下:(C++)

// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (val != nums[fastIndex]) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        return slowIndex;
    }
};

注意这些实现方法并没有改变元素的相对位置!

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

 代码如下:(C++)

/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int leftIndex = 0;
        int rightIndex = nums.size() - 1;
        while (leftIndex <= rightIndex) {
            // 找左边等于val的元素
            while (leftIndex <= rightIndex && nums[leftIndex] != val){
                ++leftIndex;
            }
            // 找右边不等于val的元素
            while (leftIndex <= rightIndex && nums[rightIndex] == val) {
                -- rightIndex;
            }
            // 将右边不等于val的元素覆盖左边等于val的元素
            if (leftIndex < rightIndex) {
                nums[leftIndex++] = nums[rightIndex--];
            }
        }
        return leftIndex;   // leftIndex一定指向了最终数组末尾的下一个元素
    }
};

 其他语言版本

Java:

class Solution {
    public int removeElement(int[] nums, int val) {
        // 快慢指针
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
            if (nums[fastIndex] != val) {
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
}

//相向双指针法
class Solution {
    public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length - 1;
        while(right >= 0 && nums[right] == val) right--; //将right移到从右数第一个值不为val的位置
        while(left <= right) {
            if(nums[left] == val) { //left位置的元素需要移除
                //将right位置的元素移到left(覆盖),right位置移除
                nums[left] = nums[right];
                right--;
            }
            left++;
            while(right >= 0 && nums[right] == val) right--;
        }
        return left;
    }
}
// 相向双指针法(版本二)
class Solution {
    public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length - 1;
        while(left <= right){
            if(nums[left] == val){
                nums[left] = nums[right];
                right--;
            }else {
                // 这里兼容了right指针指向的值与val相等的情况
                left++;
            }
        }
        return left;
    }
}

Python

(版本一)快慢指针法
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        # 快慢指针
        fast = 0  # 快指针
        slow = 0  # 慢指针
        size = len(nums)
        while fast < size:  # 不加等于是因为,a = size 时,nums[a] 会越界
            # slow 用来收集不等于 val 的值,如果 fast 对应值不等于 val,则把它与 slow 替换
            if nums[fast] != val:
                nums[slow] = nums[fast]
                slow += 1
            fast += 1
        return slow
(版本二)暴力法
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i, l = 0, len(nums)
        while i < l:
            if nums[i] == val: # 找到等于目标值的节点
                for j in range(i+1, l): # 移除该元素,并将后面元素向前平移
                    nums[j - 1] = nums[j]
                l -= 1
                i -= 1
            i += 1
        return l

 C

int removeElement(int* nums, int numsSize, int val){
    int slow = 0;
    for(int fast = 0; fast < numsSize; fast++) {
        //若快指针位置的元素不等于要删除的元素
        if(nums[fast] != val) {
            //将其挪到慢指针指向的位置,慢指针+1
            nums[slow++] = nums[fast];
        }
    }
    //最后慢指针的大小就是新的数组的大小
    return slow;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/523487.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能变电站协议系列-5、IEC 104协议细化解读(IEC 60870以及如何获取对应国标和行标)

一、前言 通过之前整体性的协议分析&#xff0c;目前确定先基于IEC104做深入分析&#xff0c;来结合分析电网常见的业务&#xff0c;以此从协议侧关联深入到业务侧。在国内该标准也应用比较稳定和广泛了&#xff0c;所以研究104协议相关资料也会更全一些。 二、资料及标准收集…

Spring Security——09,解决跨域

解决跨域 一、SpringBoot配置二、配置SpringSecurity三、修改端口四、修改vue项目4.1 拿到token4.2 前端存储token4.3 前端请求头携带token 五、测试5.1 认证测试5.2 授权测试 一键三连有没有捏~~ 浏览器出于安全的考虑&#xff0c;使用 XMLHttpRequest对象发起 HTTP请求时必须…

BugKu:Flask_FileUpload

1.打开此题 通过题目知道这个是一个关于Flask的文件上传的漏洞题目 2.查看网页源代码 Flask是一个使用Python编写的轻量级Web应用框架。 这里又提示说用python来运行结果&#xff0c;那很有可能就是要通过python脚本来抓取flag 3.编辑Python脚本 工具&#xff1a;pycharm 文件…

第十一届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组

第十一届蓝桥杯大赛软件赛省赛C/C 大学 B 组 文章目录 第十一届蓝桥杯大赛软件赛省赛C/C 大学 B 组1、字串排序2、门牌制作3、既约分数4、蛇形填数5、跑步锻炼6、七段码7、成绩统计8、回文日期9、子串分值和10、平面切分 1、字串排序 2、门牌制作 #include<iostream>#def…

服务注册 Zookeeper

服务注册 Zookeeper 1、配置并启用 Zookeeper # application.yml dubboregistryaddress: zookeeper://localhost:2181# dubbo.properties dubbo.registry.addresszookeeper://localhost:2181<dubbo:registry address"zookeeper://localhost:2181" />address …

YOLOv5实例分割

目录 一,准备工作 1.1 标签数据解释: 1.2 数据集格式转换方法汇总 图片和JSON在一个文件夹的形式,通过下面的代码会再相同文件夹下生成对应的txt文件 方式2: 二,训练、测试、检测 一,准备工作 用conda创建自己的环境 安装项目路径下的requirements.txt 数据集准备…

快速获取文件夹及其子文件夹下的所有文件名

1、在文件夹中新建文本文档&#xff0c;命名为“命令.txt” 2、输入以下内容 tree /F > 文件名.txt dir *.* /B > 文件名.txt 其中文件名和文件格式可以是任意的&#xff0c;tree命令可生成文件及其子文件夹下所有文件的名称&#xff0c;dir命令只生成当前目…

OKR管理模式:企业新引擎,驱动未来发展

在当今竞争激烈的市场环境中&#xff0c;越来越多的企业开始采用OKR&#xff08;Objectives and Key Results&#xff0c;目标与关键成果&#xff09;管理模式&#xff0c;以期解决一系列发展难题&#xff0c;驱动企业向前发展。OKR作为一种目标管理工具&#xff0c;旨在帮助企…

Java实现二叉树(上)

1.树型结构 1.1树型结构的概念 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因为它看 起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 1.2树型结构的特点…

AI预测福彩3D第28弹【2024年4月6日预测--第7套算法重新开始计算第1次测试】

今天开始&#xff0c;咱们开始进行第7套算法的测试&#xff0c;第7套算法将综合012路权重、012路直选及012路和值进行预测。好了&#xff0c;先上图后上结果吧~ 2024年4月6日福彩3D的七码预测结果如下 第一套&#xff1a; 百位&#xff1a;1 2 4 5 7 8…

基于javassm实现的列车票务信息管理系统

开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&…

Network AIS Receiver R400N

目录 Introduction OVERVIEW BASIC FEATURES APPLICATIONS SPECIFICATIONS Introduction OVERVIEW The R400N provides a method of monitoring the position, speed and heading of AIS vessels within VHF range. It can decode of Class A, Class B, Aids to Navigat…

位运算、芯片封装方式、中断、定时器

我要成为嵌入式高手之4月3、7日51单片机第一、二天&#xff01;&#xff01; ———————————————————————————— 裸机驱动&#xff1a;51 -> s3c2440 -> linux Soc片上系统 位运算 高位&#xff1a;MSB 地位&#xff1a;LSB 按位与&…

【C++第三阶段】string容器

以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 string容器基本概念构造函数赋值操作拼接操作字符串查找和替换字符串比较字符串存取字符串插入和删除字符串子串 string容器 基本概念 本质&#x1f449;string是C风格的字符串&…

php校园活动报名系统vue+mysql

开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp/Laravel 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 运行环境:phpstudy/wamp/xammp等本选题则旨在通过标签分类管理等方式&#xff0c;管理员&#xff1b;首页、个人中心、学生管理、…

EPSON推出XV-9100CD为检测车身所处姿势状态提供解决方案

陀螺仪传感器是电子稳定控制系统中不可缺少的传感器之一。与通常的民用部件相比&#xff0c;用于车载的部件有一些特殊要求。因为涉及安全&#xff0c;所以高可靠性是必备条件。在制动组件等高温条件下的耐久性、受振动或撞击时不会产生异常输出亦是十分重要的条件。爱普生推出…

Python景区票务人脸识别系统(V2.0),附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

4、双指针-移动零

首先不能复制&#xff0c;只能在原数组是哪个操作&#xff0c;那么很多集合的方式就不行了。当然在现实开发中肯定是可以的。目前按照题目来说是不可以的。所以我们可以思考下&#xff0c;是否可以通过交换来实现。 初始化一个变量 to 为 0。这个变量的目的是跟踪非零元素应该…

书籍《笔记的方法》读后感

读完《笔记的方法》有几周的时间&#xff0c;书里有些记录的内容&#xff0c;觉得非常有价值的&#xff0c;自己的观点&#xff0c;当下读书&#xff0c;其实并没有那么高大尚&#xff0c;就是存粹陶冶下情操&#xff0c;读书还是有一定作用的&#xff0c;毕竟看书只能慢慢来&a…

数字反转(StringBuffer)

题目 import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();StringBuffer s new StringBuffer();//字符串转为整型数if(n>0) {s.append(n);String ss s.reverse().toString()…