【每日一题】【LeetCode】【第三天】删除有序数组中的重复项

news2024/12/26 23:35:19

删除有序数组中重复项的解决之路= =

这个标签是简单,所以比较好过。

题干描述

根据题目描述,重点在于原地删除,也就是空间复杂度为O(1)

在这里插入图片描述

在这里插入图片描述

测试案例(部分)

在这里插入图片描述

第一次

根据题目描述,重点在于原地删除。

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for k, v in enumerate(nums):
            i = 1
            if k+i < len(nums):
                temp = nums[k+i]
            else:
                break
            while(v == temp):
                nums.remove(v)
                i += 1
                if k+i < len(nums):
                    temp = nums[k+i]
                else:
                    break
        return len(nums)

测试了代码,有错误的结果,会有重复的部分没有被删除。

在这里插入图片描述

第二次

有的测试案例可以通过,但还是有问题,比如测试序列[0,0,1,1,1,2,2,3,3,4],输出的是[0,1,1,2,3,4],与答案不符。

原因我们找一下,用手算推演了一下过程,会发现,我们这个设计的nums[k+i]的探测不合理。

比如测试序列[0,0,1,1,1,2,2,3,3,4]中,这三个1的情况,第一次检测下标为2的1和下标为3的1重复,然后删除下标为2的1;现在新的下标为2的1和下标为3的1还是重复,但是因为这个i,反而不会与下标为3的1比较,而是与2+2=4的下标比较,所以最终输出会多出一个1没有被删除。

所以,+i改成一直+1就可以了,因为删除之后会产生新的下标,不需要动态的+i

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for k, v in enumerate(nums):
            if k+1 < len(nums):
                temp = nums[k+1]
            else:
                break
            while(v == temp):
                nums.remove(v)
                if k+1 < len(nums):
                    temp = nums[k+1]
                else:
                    break
        return len(nums)

测试案例全部通过,提交试试。通过了。

在这里插入图片描述

第三次(抄的)

提交了,通过了,不过时间就击败了12%。。。

回过头来看看代码,感觉应该想不出什么更快的方案了,翻翻万能的评论区。

woc,看到了一个老哥的代码,一下就搞定了。

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        for i in range(n-1,0,-1): 
            if nums[i] == nums[i-1]: 
                nums.pop(i)
        return len(nums)

就用了28ms,比我的1084要快好多啊,没想到这样还只是击败50%。。。。简直就是36(除了6还是6)

在这里插入图片描述

后续闲聊

学习了一下这个代码思路。最主要费时间的代码就是while循环,直接用一个if就可以代替了,不需要while循环判断。

至于为什么要逆序,如果用if来写的话,从前往后删除元素的时候,从前往后通过下标来进行每轮的for循环就会产生跳元素的情况。就像下面的代码

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for i in range(len(nums)):
            if i+1 >= len(nums):
                break
            if nums[i] == nums[i+1]:
                nums.remove(nums[i])
        return len(nums)

执行测试案例,发现确实有跳元素的情况。

在这里插入图片描述

【第一轮for循环】i=0,无越界情况,比较下标为0的0和下标为1的0,发现相等,删除第一个0。
【第二轮for循环】i=1, 无越界情况,比较下标为1的1和下标为2的1,发现相等,删除第一个1。
【第三轮for循环】i=2, 无越界情况,比较下标为2的1和下标为3的2,不相等,进行下一次for循环。(跳过了一个1没有删除!

而用逆序,就不用考虑下标混乱产生的跳元素现象了。

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for i in range(len(nums)-1, 0, -1):
            if nums[i] == nums[i-1]:
                nums.remove(nums[i])
        return len(nums)

提交了,通过了,不过时间更长了。

在这里插入图片描述

再看看代码的差异,就剩pop和remove这两个差异了。关于这两个函数的描述如下:

python的列表,提供两个删除元素的方法,一个是pop,一个是remove。

pop()是通过下标删除元素,比如pop(1),就是删除下标为1的元素。

remove()是通过查找元素来删除元素,比如remove(36),就是从列表的头开始找,找到第一个等于36的元素,然后把第一个36的元素删除(还有其他36的话,不会被删除)

可能是自己的代码中,使用了remove(),这种方式删除元素,需要O(n)的复杂度。(顺序查找元素要花费O(n))按下标删除元素会更快一些。改为pop(i)时间确实快了,而且pop(i)pop(i-1)都可以。

在这里插入图片描述

不过,python中remove()的底层实现,不一定是顺序查找再删除。因为使用while循环+pop()实现功能,时间差别不大,甚至更慢。

在这里插入图片描述

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

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

相关文章

解决Linux【-bash: fork: retry: 没有子进程】

解决Linux【-bash: fork: retry: 没有子进程】问题发现问题解决设置Linux最大用户线程数设置单个用户可用最大进程数问题发现 日常工作中&#xff0c;服务器连不上&#xff0c;好在昨天登陆的服务器用户没有下线&#xff0c;然后执行任何命令时返回- bash: fork: retry: 没有子…

React(coderwhy)- 03(高阶组件+动画)

1.React性能优化SCU React更新机制 React的更新流程 ◼ React在props或state发生改变时&#xff0c;会调用React的render方法&#xff0c;会创建一颗不同的树。 ◼ React需要基于这两颗不同的树之间的差别来判断如何有效的更新UI&#xff1a;  如果一棵树参考另外一棵树进行完…

可观测产品的最佳实践,涵盖端到端的可观测解决方案丨阿里云用户组深圳站

2022 年 9 月 28 日&#xff0c;阿里云在深圳举办了第 11 场阿里云用户组&#xff08;AUG&#xff09;活动&#xff0c;活动主题“可观测性实践”吸引了众多技术从业者及企业管理者来到现场。通过本次活动&#xff0c;参会企业了解到三块内容&#xff1a;1. Java 应用最佳实验&…

小蓝本 第一本 《因式分解技巧》 第八章 多项式的一次因式 笔记 (第八天)

小蓝本 第一本 《因式分解技巧》 第八章 多项式的一次因式 笔记 &#xff08;第八天&#xff09;前言余数定理有理根求法第一步第二步(可能有理根多的情况下&#xff0c;可以用)第三步快速识别特殊有理根情况1情况2求解注意习题8题目题解改错前言 坚持的第8天&#xff0c;因为…

北大陈斌Python算法笔记(一)

前言 &#x1f340;作者简介&#xff1a;被吉师散养、喜欢前端、学过后端、练过CTF、玩过DOS、不喜欢java的不知名学生。 &#x1f341;个人主页&#xff1a;红中 &#x1f342;不就是蓝桥杯嘛&#xff0c;干他&#xff01;&#xff01;我堂堂 线性结构 线性结构是一种有序数…

优先级反转问题及解决办法

优先级反转问题及解决办法什么是优先级反转解决方法1&#xff1a;优先级继承解决方法2&#xff1a;优先级天花板总结什么是优先级反转 优先级反转&#xff0c;是指在多线程的环境下&#xff0c;并且使用了信号量时&#xff0c;可能会出现的这样一种不合理的现象&#xff0c;即…

@PostConstruct 和 @PreDestroy 使用

目录1.简介2.使用3.注意事项4.执行顺序5.测试6.测试结果1.简介 PostConstruct&#xff1a; Java 自带的注解&#xff0c;在方法上使用该注解&#xff0c;会在项目启动的时候执行被修饰的方法。 PreDestroy&#xff1a; Java 自带的注解&#xff0c;在方法上使用该注解&#xff…

element 日期选择器数据更改,第一次进入页面,页面上没有回显(数据格式问题导致)

需求 页面列表数据&#xff0c;默认是展示一个月的数据 遇到的问题 一进来页面&#xff0c;日期选择器上是空的&#xff0c;但绑定的值是有数据的&#xff0c;页面上并没正确回显&#xff0c;但是去手动选择日期&#xff0c;也是可以正常回显的 思考 其实&#xff0c;选择…

【MySQL进阶教程】 索引详细介绍

前言 本文为 【MySQL进阶教程】 索引 相关知识介绍&#xff0c;下边具体将对索引概述&#xff0c;索引结构&#xff08;包括&#xff1a;索引结构概述&#xff0c;二叉树&#xff0c;B-Tree&#xff0c;BTree&#xff0c;Hash&#xff09;&#xff0c;索引分类&#xff0c;索引…

leetcode练习之商品折扣后的最终价格(单调栈算法)

题目描述 给你一个数组 prices &#xff0c;其中 prices[i] 是商店里第 i 件商品的价格。 商店里正在进行促销活动&#xff0c;如果你要买第 i 件商品&#xff0c;那么你可以得到与 prices[j] 相等的折扣&#xff0c;其中 j 是满足 j > i 且 prices[j] < prices[i] 的 最…

JdbcUtils工具类的优化升级——通过配置文件连接mysql8.0,并对mysql8.0中的表进行[简单查询]操作

目录 一、在DogDao中新增查询的功能 二、在DogDaoImpl类中继承基类&#xff0c;并实现接口的功能 三、创建工具接口RowMapper 四、重新定义一个基类BaseDao2 五、新建一个DogDaoImpl2实现类&#xff0c;继承基类BaseDao2&#xff0c;实现DogDao接口的两个查询功能 六、在…

【Kotlin】函数 ⑧ ( 函数引用 作为函数参数 | ::函数名 | 函数类型 作为函数返回值类型 )

文章目录一、函数引用作为函数参数二、函数类型作为函数返回值一、函数引用作为函数参数 函数 作为参数 , 有两种方式 : 传递 Lambda 表达式 , 也就是 匿名函数 作为参数值 ;传递 函数引用 作为参数值 ; 函数引用 可以将 具名函数 转为 函数的参数值 , 只要可以使用 Lambda 表…

程序员真是越来越懒了,Api 文档都懒得写?程序员:Api工具惯的!

关于大多数程序员不爱写文档问题&#xff0c; 我觉得可以从两个方面去拆解&#xff1a;主观原因、客观原因。 1. 客观 - 时间紧任务重&#xff0c;需求变化快 需求方每次都是紧急需求&#xff0c;老板每次都要求敏捷开发&#xff0c;快速响应。 按时交付的压力已经让大多数程…

区分: 小程序组件 and 小程序插件

近期发现有不少小伙伴分不清小程序组件和小程序插件&#xff0c;以为它们是一回事&#xff0c;只是措辞不一样。但实际上&#xff0c;小程序组件和小程序插件完全是两回事——插件是可以直接提供服务的&#xff0c;组件是给开发者提供的轮子&#xff0c;不能直接提供服务。下面…

Java--基本数据类型

文章目录前言一、数据类型-byte二、数据类型-short三、数据类型-int四、数据类型-long五、数据类型-float六、数据类型-double七、数据类型-char八、数据类型-boolean九、数据类型实例前言 Java提供了八种基本类型&#xff0c;六种数字类型&#xff08;四个整数型&#xff0c;…

LoRa无线远传水表方案ASR6500S/LLCC68

LoRa无线远传水表就是普通机械水表加上电子采集发讯模块而组成&#xff0c;电子模块完成信号采集、数据处理、存储并将数据通过通信线路上传给中继器、或手持式的抄表器。LoRa无线远传水表作为市面上比较火的智能水表&#xff1b;由主站通过传输媒体将多个户用仪表的数据集中抄…

MyBatis讲解,批量删除1

一、批量删除1 入参字符串 ”id1,id2,id3” 批量删除的关键字是 in 1.书写BookMapper 1.1先在navicat的新建查询里书写批量删除的sql语句 批量删除的sql语句 delete from book where id in (12,22); 1.2将sql语句复制到BookMapper里 2.书写BookDao批量删除方法 *书写dao…

【安全硬件】Chap.4 如何插入一个硬件木马到芯片的时序逻辑电路的漏洞里?如何构建可信赖的状态机?

【安全硬件】Chap.4 如何插入一个硬件木马到芯片的时序逻辑电路的漏洞里&#xff1f;如何构建可信赖的状态机&#xff1f;前言&#xff1a;硬件木马1. 时序逻辑电路中的设计漏洞Design Vulnerabilities序列检测器的设计漏洞——以智能门锁的虚位密码漏洞为例易受攻击的状态机写…

Qt基础之十八:WebEngine与JavaScript交互

Qt从5.6开始就用Qt Webengine替换了Qt WebKit,据说加载速度较Qt WebKit更快。 需在pro中添加QT += webenginewidgets 一.效果 二.实现 1.JavaScript调用Qt函数 在MainWindow中定义成员变量QWebChannel *m_channel;作为和web通信的数据通道 ①加载网页 void MainWindow::l…

多线程案例-阻塞式队列

1.什么是阻塞队列阻塞队列是一种特殊的队列,在"先进先出"的原则下又引入了"阻塞"功能阻塞队列能是一种线程安全的数据结构,具有以下特性:当队列满的时候,继续入队列就会阻塞,直到其它线程从队列中取走元素当队列空的时候,继续出队列就会阻塞,直到其它队列向…