LeetCode.26,27,88三题-双指针的运用

news2024/10/7 12:21:37

本文将对3道解决方法类似的题目进行逐一分析,这三道题目分别是:

LeetCode.26 删除有序数组中的重复项

LeetCode.27 移除元素

LeetCode.88 合并两个有序数组

1. LeetCode.27 移除元素:

题目内容如下:

 假设一个数组nums为:

nums = [0,1,2,2,3,0,4,2]

元素val = 2.

按照题目的要求,需要移除数组nums中所有等于2的元素。对于此题的解析,文章提供三种参考思路

1.在之前处理顺序表中删除元素的问题时,采用的方法是将目标元素后面的元素全部向前覆盖一位。但是,这种处理方法的时间复杂度为O(N^2)过于缓慢。

2.创建一个指针和一个新的数组,遍历整个数组,在便利的过程中。若被遍历的元素大小不等于val时,将此元素复制到新开辟的数组中。当被遍历的元素大小等于val时,不复制并且将指针指向下一个元素。此方法的时间复杂度为O(N),相对于方法1,大幅度降低了程序执行所用的时间。但是,该方法因为新创建了一个数组。空间复杂度为O(N),不符合题目中的要求。

3. 虽然方法2不满足题目的要求,但是可以通过方法2的思路来延伸出方法3,也就是文章题目中提到的双指针法

对于本题,双指针法的具体用法如下:

1.创建两个指针,这里创建的指针分别命名为src,dst。最开始,两个指针都指向数组首元素的下标,即:

 对于本题中创建的两个指针的动作,总结下来就是:将数组中src位置上不等于val的元素放置到dst中。

当两个指针所对应的元素相等且不等于val时,都指向下一个元素。

当指针src对应的值等于val时,指针src指向下一个位置,dst不移动

当两个指针对应的元素不同且不等于val时,将指针src对应的元素赋值到dst位置。并且都向前移动一位。

用图片表示下列过程,即:

1.

 2.

此时, 指针src对应的值等于val。所以指针dst不动,指针src继续向后移动:

此时,指针 src对应的值不等于dst,并且不等于val。所以,进行赋值操作:

 再次向后移动,还会重复上面的动作:

当 src遍历整个数组后,数组中内容如下图所示:

上述过程对应的代码为:

int removeElement(int* nums, int numsSize, int val){
    int dst = 0;
    int src = 0;
    while( src < numsSize)
    {
        if( nums[src] != val)
        {
            nums[dst++] = nums[src++];
        }
        else
        {
            src++;
        }
    }
    return dst;

}

 2. LeetCode.88 合并两个有序数组:

题目如下:


 

给出的示例如下:
 

 用图片表示上面给出的示例,即:

 对于这道题的解法,依旧采用双指针的思想,对于每一个数组均创建一个指针。但是,如果再次采用上面从头到尾进行遍历的方法,如果再某处需要插入元素,则还是会出现顺序表中插入元素出现的问题,即:每插入一个元素,都需要将后面的元素整体后移动一位。所以对于此题。最好采用从后向前,从大到小的顺序进行遍历。并且,将第一个数组中最大的元素与第二个数组中的元素分别进行比较。较大的则插入到第一个数组中后面的区域,将上述过程用图片演示,即:

 上面的情况中,是第二个数组元素全部遍历完成时,第一个数组中的元素没有完成遍历。但是对于下面的情况,即:第一个数组完成遍历时,第二个数组并没有完成遍历:

用图片表示上述数组中元素的变化情况:

 ​​

 

 最后的结果如上图所示: 第二个数组中的元素2并没有插入到第一个数组中。并且第一个数组已经遍历完成。而第二个数组没有遍历完成。

总结上述过程,为了方便陈述,将第一个数组命名为nums1,将第二个数组命名为nums2

nums1创建的指针命名为dst,为nums2创建的指针命名为src

从后向前对两个数组同时遍历,

当满足src对应的元素>dst对应的元素时,将src对应的元素在nums1中进行一个尾插操作。并且两个指针均指向前一个元素。

当不满足上述关系时,将dst对应的元素在nums1在前面插入元素的基础上进行一个尾插操作。并将dst指向前一个元素。

nums2遍历完成时。标志着程序运行完成。当nums1遍历完成但是nums2没有完成遍历时。将nums2剩余的元素在nums1中进行插入。

用代码表示上述过程:

首先,题目中已给的参数分别是:

m表示 nums1中非0的元素。n表示nums2中的元素。为了方便表示,用end1,end2表示上面的参数。end表示nums1中加上0元素的总长度。

代码如下:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int end1 = m - 1; 
    int end2 = n -1;
    int end = m + n -1;
   while( end1 >= 0 && end2 >= 0)
   {
       if( nums1[end1] > nums2[end2])
       {
           nums1[end--] = nums1[end1--];
       }
       else
       {
           nums1[end--] = nums2[end2--];
       }
   }
       while( end2 >= 0)
       {
           nums1[end--] = nums2[end2--];
       }

}

3. LeetCode. 26 删除有序数组中的重复项:

题目如下:

 示例如下:

依旧采用双指针的方法来结局问题。创建两个指针分别为src,dst

从上面的题目要求可知。题目涉及到对于数组中元素的更改。所以,创建的两个指针在开头可以处于相同位置,也可以处于不同位置。为了方便演示,这里给出不同位置的情况,例如下面图片所示的数组:

 

 因为要保证数组中元素不能重复,所以,需要将后面的元素覆盖到前面元素的位置。所以,需要一个指针取读取后一位的元素,并且与前一位的元素进行对比。此时如果后一位元素与本位元素相同。则src指向后一个元素:

 此时,两个指针指向的元素不同,所以,先让dst指向后一位元素,再将src中的元素赋值给此时的dst,再src+1,此时两个指针指向的元素相同,所以一直src+1,直到:

 重复上面所说的步骤,即:

 

 按照前面说的规则,最后的效果为

 

通过图片不难发现,程序结束的标志就是当指针src <= 数组中元素个数-1时(或者src <数组中元素个数时)。

总结上述过程,可以分为三个要点:

1. src < 数组中元素个数时,程序结束

2.src指向的值=dst时,src指向后面的元素。dst不变。

3. src指向的值不等于dst时,先将dst+1,再将src+1指向的值赋值到dst,最后src+1.

用代码表示,即:

int removeDuplicates(int* nums, int numsSize){
    int dst = 0;
    int src = 1;
  while( src < numsSize)
  {
      if( nums[src] == nums[dst])
      {
          src++;
      }
      else
      {
          dst++;
          nums[dst] = nums[src];
          src++;
      }
  }
    return dst+1;

}

 


 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp+vue3+vite+pinia2.0.33项目初始化

目录 准备工作 注意事项 使用vue-cli创建项目 运行 准备工作 下载hbuild开发工具 HBuilderX-高效极客技巧 下载微信小程序开发工具 概览 | 微信开放文档 uniapp uni-app官网 注意事项 1.node.js版本>16#windows查看node版本 C:\Users\22862>node -v v18.16.0 …

02Mysql之多表查询--例题讲解

一、题目详情&#xff0c;以及表的建立 新增员工表emp和部门表deptcreate table dept (dept1 int ,dept_name varchar(11));create table emp (sid int ,name varchar(11),age int,worktime_start date,incoming int,dept2 int);insert into dept values(101,财务),(102,销售)…

【数据中台商业化】数据中台微前端实践

一&#xff0c;需求背景 1 业务背景 在以往的业务场景中&#xff0c;用户进入五花八门的菜单体系中&#xff0c;往往会产生迷茫情绪&#xff0c;难以理解平台名称及具体作用&#xff0c;导致数据开发与管理学习成本较高&#xff0c;降低工作效率。为此我们整合从数据接入&…

不知道打仗之害,就不知道打仗之利

不知道打仗之害&#xff0c;就不知道打仗之利 【安志强趣讲《孙子兵法》第7讲】 【原文】 夫钝兵挫锐&#xff0c;屈力殚货&#xff0c;则诸侯乘其弊而起&#xff0c;虽有智者&#xff0c;不能善其后矣。 【注释】 屈力殚货&#xff1a;屈力&#xff0c;指力量消耗&#xff0c;…

掌握Python的X篇_32_使用python编辑pdf文件_pdfrw

本篇介绍利用python操作pdf文件&#xff0c;我们平时也会有合并和拆分pdf的需求&#xff0c;此时我们就可以使用本节内容。 文章目录 1. pdfrw的安装2. 切分pdf文件3. pdfrw官网及实现一版四面的实例 1. pdfrw的安装 pip install pdfrw官网地址&#xff1a;https://github.co…

设计模式之责任链模式【Java实现】

责任链&#xff08;Chain of Resposibility&#xff09; 模式 概念 责任链&#xff08;chain of Resposibility&#xff09; 模式&#xff1a;为了避免请求发送者与多个请求处理者耦合在一起&#xff0c;于是将所有请求的处理者 通过前一对象记住其下一个对象的引用而连成一条…

Mysql中插入数据,并返回自增主键的值

创建数据库和表使用 insert into 进行插入数据使用 RETURN_GENERATED_KEYS 进行返回插入的这条数据 具体方法如下&#xff1a; Testvoid addGetPk(){try{Statement stmt conn.createStatement();String sql String.format("insert into t_students values(null,%s,%s,%d…

Git:在本地电脑上如何使用git?

git 版本&#xff1a; 2.40.1.windows.1 文章目录 一. 使用git之前你必须要理解的几个概念1.1 理解工作区、版本库、暂存区的概念1.2 提交Git版本库的步骤【分两步执行】 二. Git本地库实战2.1 初始化版本库2.2 新建 & 提交 & 状态2.3 查看日志2.4 回退 & 穿梭 &am…

Linux驱动-基于Buildroot构建系统镜像后实现基于QT项目开发之环境配置

Linux驱动-基于Buildroot构建系统镜像后实现基于QT项目开发之环境配置 需求BuildRootUboot的仓库地址和commit idKernel 的仓库地址和commit id BuildRoot已编译库在Windows上的Create上创建项目编译QT项目 需求 基于Build root编译整个镜像后&#xff0c;如何开发自己的基于Q…

D* 算法完全解析(应该是全网最详细的吧)

花了几天时间学习了下 D* 算法&#xff0c;只能说熟悉了一下流程&#xff0c;远不能说掌握&#xff0c;算法实在是非常巧妙 参考 《制造车间无人搬运系统调度方法研究》 《基于D*Lite算法的移动机器人路径规划研究》 人工智能: 自动寻路算法实现(四、D、D*算法) D* 算法 D*路径…

Pycharm社区版连接WSL2中的Mysql8.*

当前时间2023.08.13&#xff0c;Windows11中默认的WSL版本已经是2了&#xff0c;在WSL2中默认的Ubuntu版本已经是22.04&#xff0c;而Ubuntu22.04中默认的Mysql版本已经是8.*。 Wsl 2 中安装mysql WSL2中安装Mysql的方法参考自微软官方文档【开始使用适用于 Linux 的 Windows …

网络请求中,token和cookie有什么区别

HTTP无状态&#xff0c;每次请求都要携带cookie&#xff0c;以帮助识别用户身份&#xff1b; 服务端也可以向客户端set-cookie&#xff0c;cookie大小限制为4kb&#xff1b; cookie默认有跨域限制&#xff0c;不跨域共享和传递&#xff0c;例如&#xff1a; 现代浏览器开始禁…

使用Python和pyodbc库将文件信息插入Access数据库

将文件信息插入 Access 数据库的博客文章示例&#xff1a; 简介&#xff1a; 在日常编程工作中&#xff0c;我们经常需要处理文件和文件夹。有时&#xff0c;我们需要遍历文件夹中的所有文件&#xff0c;并将文件的路径、类型、文件名以及修改日期和创建日期等信息保存到数据库…

基于MIV的神经网络变量筛选

1.案例背景 一般神经网络中所包含的网络输人数据是研究者根据专业知识和经验预先选择好的,然而在许多实际应用中,由于没有清晰的理论依据,神经网络所包含的自变量即网络输入特征难以预先确定,如果将一些不重要的自变量也引入神经网络,会降低模型的精度,因此选择有意义的自变量特…

Flask 上下文是什么 ?

哈喽大家好&#xff0c;我是咸鱼。今天我们来聊聊什么是 Flask 上下文 咸鱼在刚接触到这个概念的时候脑子里蹦出的第一个词是 CPU 上下文 今天咸鱼希望通过这篇文章&#xff0c;让大家能够对 Flask 上下文设计的初衷以及应用有一个基本的了解 Flask 上下文 我们在使用 Flask 开…

【算法基础19-模拟队列】

模拟队列 算法示意图 算法的伪代码 例题 实现一个队列&#xff0c;队列初始为空&#xff0c;支持四种操作&#xff1a; push x – 向队尾插入一个数 x&#xff1b;pop – 从队头弹出一个数&#xff1b;empty – 判断队列是否为空&#xff1b;query – 查询队头元素。 现在要…

不做Linux就没前途吗?

答案当然是——并不会 我晚上回来的时候跟一个今年的毕业生聊天&#xff0c;他入职了一家公司&#xff0c;但是从事的不是Linux相关的工作。 我这里想说的是&#xff0c;做Linux可以赚钱&#xff0c;Linux现在是全世界最牛逼的开源项目一点都不为过&#xff0c;但是Linux也不是…

环境与能源创新专题:地级市绿色创新、碳排放与环境规制数据

数据简介&#xff1a;推动绿色发展&#xff0c;促进人与自然和谐共生是重大战略举措。绿色发展强调“绿水青山就是金山银山”&#xff0c;人与自然和谐共生重在正确处理生态环境保护与经济发展的关系。在着力于实现绿色发展的过程中&#xff0c;绿色创新是绿色发展的重要驱动因…

时序预测 | Matlab实现基于RF随机森林的电力负荷预测模型

文章目录 效果一览基本介绍模型描述源码设计学习小结参考资料效果一览 基本介绍 时序预测 | Matlab实现基于RF随机森林的电力负荷预测模型 电力负荷预测是指通过对历史电力负荷数据分析,来预测未来某个时间段内的电力负荷需求。这项预测对于电力系统的运行和调度至关重要,可以…

CSS实现左侧固定,右侧自适应(5种方法)

<div class"father"><!-- 左右div不能调换顺序来写 --><div class"left">固定宽度区</div><div class"right">自适应区</div> </div> 一、利用左侧浮动float右侧margin-left /* 利用浮动floatmargin…