(Python)LeetCode 26:删除有序数组中的重复项

题目:

分析:

这道题一拿到手我想的是直接通过循环来解决,实际上这样是可以的,只是可能耗时久一些,但是我想着是个简单题应该不会考虑时间的限制等等,于是,,我提交了,最开始的代码如下(傻瓜办法):

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        i = 0
        while i < len(nums):
            j = i + 1
            while j < len(nums):
                if nums[i] == nums[j]:
                    k = j + 1
                    while k < len(nums):
                        nums[k-1] = nums[k]
                        k += 1
                    del nums[-1]
                else:
                    j += 1
            i += 1
        return len(nums)

这种方法果然是行不通,最后一个测试用例有很多数据,通过这么多循环果然是超时了。

 于是,,我想了另一种方法,可以先转换为字典,统计字典中每个元素的个数,这些都有封装好的方法,直接调用就可以,最后实现代码如下:

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        List = dict(Counter(nums))  #Counter统计个数 dict转为字典
        nums.clear()    # 将原来的nums清空掉
        for item in List:
            nums.append(item)   # 添加元素(不重复)
        return len(nums)

这里由于题目有限制不能超过O(1)的空间,并且nums是一个引用,而不是直接的一个数组,如果没有把nums清空,而是用了另外一个列表来存储这些去重后的元素,比如array,虽然这个新的列表(array)是没有重复的,但是nums列表本质上依然没变,返回的array的长度只是会把nums列表截取而已,那么最后返回的nums仍然是前面的几个数,并没有办法做到去重这个操作,因为实际上最终我们返回的是一个长度,nums会根据这个长度截断列表,所以这些截取的数仍可能有重复,如下:

array = []

for item in List:

        array,append(item)

return len(array)

这种是有误的,nums列表本质上没发生变化,array和nums是不同的列表,地址也不同

所以我直接就把nums清空,然后给nums添加新的数据,直接对nums这个引用操作,也就是对应的列表的操作。

后来我对第一种方法也进行了改进,我就不信循环写不了,,所以后来改变了思路,原本是三重循环,考虑到第三重循环如果有很多个重复的,需要循环执行很多次,所以这里做了改变,对于有重复的先做一个记号,因为数据最大是10000,所以我这里随便设了一个数,直接统计,i 和 j 的变化也比之前更好一些,如果当前 i 和 j 下标的不一样,那么 i 和 j 后面的肯定不重复(因为元素是按序排列的),所以 i 和 j 都同时+1,然后接着判断,如果有一样的,只有 j 发生变化,并且标记,直到 nums[i] 和 nums[j] 不同,则将 i 放到 j 当前的位置,然后 j + 1 ,这里可以作图理解,其实很好理解,流程图也放上来了,可以根据流程图理解。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        i = 0
        while i < len(nums):
            j = i + 1
            while j < len(nums):
                if nums[i] != nums[j]:
                    i = j
                    j += 1
                else:
                    nums[j] = 100000   # 把重复的标记一个记号,后面直接删除掉
                    j += 1
            i += 1
        k = 0
        while k < len(nums):
            if nums[k] == 100000:   # 当判断是重复的,直接del删掉
                del nums[k]
            else:
                k += 1
        return len(nums)

不过这种方式确实,,速度是真的慢,执行用时1100ms,而上面的方法只需要40ms

结果:

 

 关于LeetCode的解题方法欢迎大家一起讨论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值