题目:
分析:
这道题一拿到手我想的是直接通过循环来解决,实际上这样是可以的,只是可能耗时久一些,但是我想着是个简单题应该不会考虑时间的限制等等,于是,,我提交了,最开始的代码如下(傻瓜办法):
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的解题方法欢迎大家一起讨论~