每日精讲:删除有序数组中的重复项,移除元素,合并两个有序数组

一       移除元素

     1题目链接27. 移除元素 - 力扣(LeetCode)

      2题目描述:

         给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

        假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 

     

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2,_,_]
解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。

3思路:这里有很多种比如我们先合并两个数组在进行排序,但是由于这种方法的时间空间复杂度太大所以我们一般不采用这种发放。这里我们使用简便方法双指针法(不是创建两个指针而是创建俩个变量分别指向数组的俩个位置)

示例 1:为例

这里我们定义两个变量让他们指向数组的头部,让src做探头判断是否与val值相等

dst用于站岗。

这里有两种情况即nums[src]等于val的值和nums[src]不等于val的值

1当nums[src]==val时,src++

2当nums[src]!=val时,先赋值nums[dst]=nums[src],再dst++,src++

我们这里用src1当探头所以当src==numsSize时跳出循环,因为只有nums[src]!=val时,dst++所以此时dst的值就是不等于 val 的元素的个数所以我们返回dst的值便可

代码实现

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

可以看到分支语句中有重复代码,可以进一步优化

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

 

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

   1   题目链接:26.删除有序数组中的重复项

   2   题目描述:

        给你一个 非严格递增排列的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。


示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]


解释:函数应该返回新的长度

2

并且原数组 nums 的前两个元素被修改为

1,2

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

3思路:因为数组是一个非严格递增排列的数组所以重复项一定相邻,这里也有很多方法这里我们使用双指针法。

示例 1:为例

     这里创建两个变量让它们分别指向数组起始位置和下一个位置,依次判断指向数组元素的值是否相等,所以我们这里有两种情况。

在src往后遍历中:

        1.nums[dst] == nums[src],src++

        2.nums[dst] != nums[src],dst++,nums[dst] = nums[src],src++ 

       当src == numsSize时,跳出循环,此时dst+1等于有效数据k,最后返回dst即可。

       这里我们有一个重要问题就是当第二种情况中dst==src时赋值和不赋值都一样这就存在重复赋值所以我们要进入第二步我们可以加入两个条件即( .nums[dst] != nums[src]  && src != dst)。

代码实现

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

可以看到分支语句中有重复代码,可以进一步优化

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

三      合并两个有序数组

1题目链接:88. 合并两个有序数组 - 力扣(LeetCode)

2题目描述:

        给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你合并 nums2 到 nums1 中,使合并后的数组同样按非递减顺序排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

3思路:

      3.1思路一:先合并数组,在对数组进行排序

             以实例1为例,合并后数组:(合并后再对数组进行冒泡排序或快速排序,这里以冒泡排序实现)

代码实现


void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    if (nums2 == NULL)
    {
        return;
    }
   //合并数组
   int l1 = m;
   int l2 = 0;
   int l3 = m + n;
   while(l1 < l3)
   {
    nums1[l1++] = nums2[l2++];
   }
   //排序
   for (int i = 0;i<l3-1;i++)
   {
    for (int j = 0;j<l3 - 1 - i;j++)
    {
        if (nums1[j]>nums1[j+1])
        {
            int tmp = nums1[j];
            nums1[j] = nums1[j+1];
            nums1[j+1] = tmp;
        }
    }
   }

}

时间复杂度O(n^2) ,空间复杂度O(1)

3.2思路二:从后往前遍历数组

因为两个数组都是非递减顺序 排列的整数数组所以我们只要不断比较两个数组中最大的元素

再让大的值存人数组的最后依次遍历。

当其中一个数组遍历完就结束循环,这时就有两种情况分别是

数组1越界,将nums2中剩余元素按从后往前的顺序导入l1中。 

数组2越界,说明nums2中元素已经排序完成。

这里我们定义l1指向nums1数组中的尾元素l2指向nums2数组中的尾元素l3指向nums1数组的尾部。 

int l1 = m - 1;
int l2 = n - 1;
int l3 = m + n - 1;
while(l1>=0 && l2>=0)
{
     if (nums1[l1] > nums2[l2])
     {
        nums1[l3--] = nums[l1--];
     }
     else{
        nums1[l3--] = nums2[l2--];
     }
}

控制循环条件为l1与l2不越界,在循环中从后往前比大小,大的元素放在数组尾部。

        跳出循环时:(两种情况)

若l1>=0为假,l1越界,将nums2中剩余元素按从后往前的顺序导入l1中。 

若l2>=0为假,l2越界,说明nums2中元素已经排序完成。

while(l2>=0)
{
   nums1[l3--] = nums2[l2--];
}
完整代码:
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int l1 = m - 1;
    int l2 = n - 1;
    int l3 = m + n - 1;
    while(l1>=0 && l2>=0)
    {
        if (nums1[l1] > nums2[l2])
        {
            nums1[l3--] = nums1[l1--];
        }
        else{
            nums1[l3--] = nums2[l2--];
        }
    }    
    //若l1>=0为假,l1越界,将nums2中剩余元素按从后往前的顺序导入l1中
    while(l2>=0)
    {
        nums1[l3--] = nums2[l2--];
    }
    //若l2>=0为假,l2越界,说明nums2中元素已经排序完成
}

与思路一相比时间复杂度降为O(n)

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

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

相关文章

Docker-技术架构演进之路

目录 一、概述 常见概念 二、架构演进 1.单机架构 2.应用数据分离架构 3.应用服务集群架构 4.读写分离 / 主从分离架构 5.引入缓存 —— 冷热分离架构 6.垂直分库 7.业务拆分 —— 微服务 8.容器化引入——容器编排架构 三、尾声 一、概述 在进行技术学习过程中&am…

关于使用带elementplus前缀图标的步骤

关于使用带elementplus前缀图标的步骤 官网 安装 | Element Plus 1.需要全局注册 2.使用某个图标时导入&#xff0c; 如 import { Search } from element-plus/icons-vue

DPVS-3: 双臂负载均衡测试

测试拓扑 双臂模式&#xff0c; 使用两个网卡&#xff0c;一个对外&#xff0c;一个对内。 Client host是物理机&#xff0c; RS host都是虚拟机。 LB host是物理机&#xff0c;两个CX5网卡分别在两个子网。 配置文件 用dpvs.conf.sample作为双臂配置文件&#xff0c;其中…

买股票的最佳时机 - 2

买卖股票的最佳时机 III 题目描述&#xff1a; 提示&#xff1a; 1 < prices.length < 1050 < prices[i] < 105 分析过程&#xff1a; 写动态规划&#xff0c;我们需要考虑一下问题&#xff1a; 定义状态状态转移方程初始条件 遍历顺序 4种状态&#xff1a; …

数据分析与算法设计-作业2-拉普拉斯算子空间滤波和增强

作业2 题目 对Flower.dat图像&#xff08;10241024&#xff0c;np.uint8&#xff09;用如下拉普拉斯算子进行空间滤波和增强&#xff1a;np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]])&#xff0c;图像边缘采用复制填充方式&#xff0c;不使用其他第三方库&#xff0c;使…

SpringBoot+Vue+微信小程序的猫咖小程序平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当下这个高速发展的时代&#xff0c;网络科技正以令人惊叹的速度不断迭代更新。从 5G …

基于SpringBoot的二手交易系统

系统展示 用户前台界面 管理员后台界面 系统背景 在当今社会&#xff0c;随着电子商务的蓬勃发展和人们消费观念的转变&#xff0c;二手物品交易逐渐成为了一种新的生活方式。人们越来越倾向于将不再需要的物品进行二次交易&#xff0c;以实现资源的有效利用和环保理念的实践。…

vscode无法预览Markdown在线图片链接

问题&#xff1a;在VSCode中&#xff0c;打开MarkDown文件&#xff0c;存在在线图片链接&#xff0c; 但是在预览时却无法显示。 原因&#xff1a;因为Visual Studio Code中的MarkDown默认配置中只允许载入安全内容 解决方法&#xff1a; 1、输入快捷键 Ctrl Shift P 打开…

Power Query M函数

文章目录 三、PQ高阶技能&#xff1a;M函数3.1 M函数基本概念3.1.1 表达式和值3.1.2 计算3.1.3 运算符3.1.4 函数3.1.5 元数据3.1.6 Let 表达式3.1.6 If 表达式3.1.7 Error 3.2 自定义M函数3.2.1 语法3.2.2 调用定义好的自定义函数3.2.3 直接调用自定义函数3.2.4 自定义函数&am…

election靶机渗透测试

发现靶机ip地址 使用nmap进行扫描端口发现详细信息nmap -T4 -sV -sC -p- 192.168.52.142 用dirsearch扫一下网站的目录 看到一个phpinfo 一个phpmyadmin的登录页面 robots.txt文件 看一下这个election目录下并没有发现什么 继续进行目录扫描&#xff0c;这时候看到一个admin的l…

为AI聊天工具添加一个知识系统 之119 详细设计之60 圣灵三角形和Checker 之2

本文要点 要点回顾 我们回顾一下本题目的讨论内容。 我的想法是&#xff0c; 将Substance 作为 面向服务的架构的起点并基于差异来自下而上地分类 实体--目的是实体职责单一化&#xff0c;将Object作为面向对象的语义差异的系统原点 并沿着差异继承的路径来至上而下地划分对…

安全生产月安全知识竞赛主持稿串词

女:尊敬的各位领导、各位来宾 男:各位参赛选手、观众朋友们 合:大家好&#xff5e; 女:安全是天&#xff0c;有了这一份天&#xff0c;我们的员工就会多一份幸福&#xff0c; 我们的企业就会多一丝光彩。 男:安全是地&#xff0c;有了这一片地&#xff0c;我们的员工就多了一…

五、Three.js顶点UV坐标、纹理贴图

一部分来自1. 创建纹理贴图 | Three.js中文网 &#xff0c;一部分是自己的总结。 一、创建纹理贴图 注意&#xff1a;把一张图片贴在模型上就是纹理贴图 1、纹理加载器TextureLoader 注意&#xff1a;将图片加载到加载器中 通过纹理贴图加载器TextureLoader的load()方法加…

Deepin(Linux)安装MySQL指南

1.下载 地址&#xff1a;https://downloads.mysql.com/archives/community/ 2.将文件解压到 /usr/local 目录下 先cd到安装文件所在目录再解压&#xff0c;本机是cd /home/lu01/Downloads sudo tar -xvJf mysql-9.2.0-linux-glibc2.28-x86_64.tar.xz -C /usr/local3.创建软链…

[MDM 2024]Spatial-Temporal Large Language Model for Traffic Prediction

论文网址&#xff1a;[2401.10134] Spatial-Temporal Large Language Model for Traffic Prediction 论文代码&#xff1a;GitHub - ChenxiLiu-HNU/ST-LLM: Official implementation of the paper "Spatial-Temporal Large Language Model for Traffic Prediction" …

Aseprite绘画流程案例(1)——画相机图标

原图&#xff1a; 步骤一&#xff1a;打开需要参照的图标 步骤二&#xff1a;将参照的图片拖放到右边&#xff0c;作为参考 步骤三&#xff1a;新建24x24的画布&#xff0c;背景为白色的画布 步骤四&#xff1a;点击菜单栏——视图——显示——像素网格&#xff08;如果画布已经…

计算机毕业设计SpringBoot+Vue.js母婴商城(源码+LW文档+PPT+讲解+开题报告)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Springboot + Ollama + IDEA + DeepSeek 搭建本地deepseek简单调用示例

1. 版本说明 springboot 版本 3.3.8 Java 版本 17 spring-ai 版本 1.0.0-M5 deepseek 模型 deepseek-r1:7b 需要注意一下Ollama的使用版本&#xff1a; 2. springboot项目搭建 可以集成在自己的项目里&#xff0c;也可以到 spring.io 生成一个项目 生成的话&#xff0c;如下…

Android输入事件传递流程系统源码级解析

1. 硬件层到Linux内核 设备节点&#xff1a;触摸事件由内核驱动捕获&#xff0c;写入/dev/input/eventX。关键结构体&#xff1a;input_event&#xff08;包含时间戳、类型、代码、值&#xff09;。 2. Native层处理&#xff08;system_server进程&#xff09; 2.1 EventHub …

贪心算法

int a[1000], b5, c8; swap(b, c); // 交换操作 memset(a, 0, sizeof(a)); // 初始化为0或-1 引导问题 为一个小老鼠准备了M磅的猫粮&#xff0c;准备去和看守仓库的猫做交易&#xff0c;因为仓库里有小老鼠喜欢吃的五香豆&#xff0c;第i个房间有J[i] 磅的五香豆&#xf…