当前位置: 首页 > news >正文

【LeetCode题目详解】(一)27.原地移除元素、88.合并两个有序数组

目录

一、力扣第27题:原地移除元素

1.思路一:

2.思路二

3.思路三

 二、力扣第88题:合并两个有序数组

1.思路一:

2.思路二:

3.思路三:

总结


一、力扣第27题:原地移除元素

题目链接:27. 移除元素 - 力扣(Leetcode)

题目描述:

1.思路一:

其实对于这道题而言,我们一开始最先想到的方法是这样的

假设我们有这样一个数组

我们先遍历一遍数组,寻找2,找到2以后,让后面的所有数据去全部依次覆盖,最后让数组当前的元素个数-1.

 然后继续遍历

 最后一次删除

就这样我们就删除了所有的元素,这种方法思考起来很简单,但其实是行不通的,因为时间复杂度太大了

我们计算时间复杂度是看最坏的情况,试想一下,我们最坏的情况就是全部的元素都需要删除,那么他的时间复杂度将达到N*(N-1+N-2+N-3+.....+1) ,因为我们本身就需要对整个数组进行一次遍历,第一个数据的删除一n-1次,第二个数据的删除要n-2次....最后一个数据的删除要1次。这个时间复杂度已经达到了立方级别,相当的大。

2.思路二

我们是这样想的,既然思路一的时间复杂度如此之大,那么我们可不可以这样思考,在开辟一个数组空间,将原来数组的值不等于2的数据依次拷贝到新的数组中。最后再把新数组的值拷贝到原来数组中。这样的话,我们就只需要一次遍历即可,这样时间复杂度就达到了O(N)

 但是这样违背了提议,因为我们的空间复杂度也变成了O(1),所以这个方法肯定是不可以的

3.思路三

我们其实可以在思路二上进行改良,使用两个指针来实现我们的目的

如下图所示,我们定义两个指针src和dest。让他们都指向第一个元素

然后我们让src往后走,如果src的位置不是val,就将他放到dest的位置,然后两个指针都++

如果src的位置是val,那就只让src++

下面是第一步移动,src指向的不是2,所以两个指针都往后移动

 这是第二步移动src指向的不是2,所以两个指针都往后移动

 这是第三次移动src指向的是2,所以src移动

这是第四次移动src仍然指向的是2,所以继续src往后移动

这是第五次移动,此时src指向的不是2,所以将3赋给dest所指向的值,两个指针都移动

 这是第六次移动,src指向的不是2,所以将src的值赋给dest,然后两个指针都向后移动

 这是第七次移动,src指向的不是2,所以src的值赋给dest,然后两个指针都向后移动

这是第八次移动,src指向的仍然不是2,所以src要继续向后移动

 此时src已经超出了数组的长度,所以现在遍历结束。dest之前,不包含dest本身的元素就是删除完2以后的数组,并且dest也代表的数组的长度,总共是5个元素

所以说这道题思路我们就想明白了,接下来就让我们来实现一下吧

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

 已通过力扣用例

 二、力扣第88题:合并两个有序数组

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

题目描述:

1.思路一:

对于这道题,我们应该能想到之前做过的一个题,也是合并两个有序数组,不过有所不同的是,那道题是将元素都放到第三个数组中,而这道题都是放在第一个数组中,这样一来,我们当然可以用之前那种思路,先弄一个第三个数组,然后放进去,然后将第三个数组的元素都弄到第一个数组中,但是这样显得太过于啰嗦了。而且空间复杂度也变大了。我们最好另寻他法

2.思路二:

和之前那道题目一样,我们可以不管什么东西,全部放在第一个数组中,然后对他进行排序。但是这样时间复杂度又变得很大了。

3.思路三:

我们这个思路是建立在第一个思路之上的,我们知道,正难则反。所以我们可以从反面来进行解答这道题,我们放在第三个数组中的思想是,找小的,然后放在第三个数组中,那我们这道题可以从最大的开始,找最大的数,放在第一个数组的最后一个位置。

我们画图来模拟一下我们的思路,如下图所示,我们创建三个变量,一个是end1用于记录数组1的下标的,一个是end2用于记录数组2的下标。然后就是end用于记录合并之后的数组下标

我们先让nums1[end1]和nums[end2]比较

如果nums1[end1]大,那么让nums1[end1]的值放入nums1[end]中,然后让end1--,end--

如果nums2[end2]大,那么让nums2[end2]的值放入nums1[end]中,然后让end2--,end--

如果最终end2<0了,那么直接停止即可

如果最终end1<0了,那么将nums2中剩余的元素放入nums1中

我们来模拟一下这个流程

第一次移动,6比3大,所以6移动到最后,end2和end--

 第二次移动,5比3大,所以5移动,end和end2--

 第三次移动,3比2大,所以3移动,end1和end--

 第四次移动,两者一样大,随意移动一个即可,我们选择移动下面的。这样end2和end--

然后end2<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];
            end--;
            end1--;
        }
        else
        {
            nums1[end]=nums2[end2];
            end2--;
            end--;
        }
    }
    while(end2>=0)
    {
        nums1[end]=nums2[end2];
        end--;
        end2--;       
    }
}

总结

本次主要讲解了两道力扣题目:27.原地移除元素、88.合并两个有序数组

希望对大家有所帮助,如果对你有帮助,不要忘记一键三连哦!!!

想要知道后续更多更精彩的内容, 一定要关注我哦!!!

相关文章:

  • 【檀越剑指大厂—Nginx】Nginx篇
  • Nacos配置管理
  • 【C进阶】第十篇——数据在内存中的存储
  • Qt实现全局鼠标事件监听器-Windows
  • 基于LEACH和HEED的WSN路由协议研究与改进(Matlab代码实现)
  • JDBC连接数据库详解~
  • 【Docker】解决Docker创建Tomcat容器实例后访问Tomcat主页时报HTTP状态404-未找到的错误
  • GitLab安装与卸载
  • Python编程 圣诞树教程 (附代码)程序员的浪漫
  • 冰雪旅游热开启!IU酒店与您畅游山水之间
  • 详解vue中watch的用法
  • CH36X系列接口芯片Linux系统开发库说明
  • 为什么char a[]的a不能用a=“hello”来赋值?
  • SpringBoot简单优雅实现图片上传功能(超详细)
  • SpringBoot整合Mybatis-Plus分页失效
  • 10.每天进步一点点---Python-Requests HTTP 请求库-2
  • 鸿蒙开发初体验以及遇到的几点坑
  • AI 实战篇 |基于 AI开放平台实现 【植物识别】 功能,成为行走的百科全书
  • 9 个神奇的 Python 技巧,让你的代码更优雅
  • Roson的Qt之旅 #136 Qt实现截图功能
  • 烟花、美食和购物优惠都安排上了,上海多区开启热闹模式
  • 广东雷州农商行董事长、原行长同日被查
  • 中国海警局新闻发言人就菲律宾非法登临铁线礁发表谈话
  • 当智驾成标配,车企暗战升级|2025上海车展
  • 杨荫凯履新浙江省委常委、组织部部长,曾任中央财办副主任
  • 预热苏杯,“谁羽争锋”全国新闻界羽毛球团体邀请赛厦门开赛