问题描述
懒得写
思路
nums
是给定数组,我计划建立一个temp
数组,存储nums
中不重复的值。
然后反过来遍历nums
,将nums
的前len[temp]
个值改为对应的temp值。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
temp = []
for val in nums:
if val not in temp:
temp.append(val)
for i in range(len(temp)):
nums[i] = temp[i]
return len(temp)
但是成绩太拉了,真是八嘎。
为啥呢?
其实多考虑了,题目是有序数组,可以借助大小关系删除重复项来着。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
del_list = []
for i in range(len(nums) - 1):
if nums[i] == nums[i+1]:
del_list.append(i)
# nums = [nums[j] for j in range(len(nums)) if j not in del_list]
del_list.sort(reverse = True)
for i in del_list:
nums.pop(i)
return len(nums)
霍,好多了,我心甚慰,从击败14%到40%了。
这样做的思路是:
- 先创建一个
del_list
,用来存储需要删除的重复值的索引。 - 遍历
nums
,如果前数=后数,则代表这俩值重复了,把前数的索引用append
方法添加到del_list
中。 - 现在就想怎么删除了。用
del
方法?不行,del
完,nums
的长度会发生变化,到最后会发生索引超出nums
的错误。 - 这里用了栈的
pop()
方法。假如del_list = [1, 3, 5]
,假如依次pop,到最后必定还会超出索引。所以先将del_list
按照倒序排序一下,再倒过来pop
。
but,我现在一想,我都把del_list
倒过来了,干嘛还要pop
?我这时候直接del
不行吗?我傻了,好像行啊。好吧,把nums.pop[i]
换成del(nums[i])
,好了,这下击败60%了。
为什么不问问chatgpt呢?
可以使用双指针法来实现删除有序数组中的重复项。
具体操作如下:
- 定义两个指针:
slow
和fast
,初始值均为0
。 - 遍历数组,当
fast
指向的元素与slow
指向的元素相同,则fast
向后移动一位; 当fast
指向的元素与slow
指向的元素不同,则将fast
指向的元素赋值给slow + 1
的位置, 并同时将slow
和fast
都向后移动一位。 - 遍历结束后,
slow
的位置即为新数组的长度。
下面是代码实现:
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
n = len(nums)
if n == 0:
return 0
slow = 0
for fast in range(1, n):
if nums[fast] != nums[slow]:
slow += 1
nums[slow] = nums[fast]
return slow + 1
emmm,让我康康啊,这里首先判断了nums
是不是空列表,如果是,就返回0
。
接下来,定义slow
为0
,其实就是指向nums
中第一个数,然后fast
从第二个数开始遍历,如果fast
指向的数不等于slow
指向的数,代表这俩数不是重复项,把slow
往后移一位,让背后将fast
指向的数赋值给slow
指向的数。
想象一下,假如nums = [1, 2, 2, 4, 4, 5]。
- 一次循环,比较第一个和第二个数,不是重复项的话就当无事发生,因为原地赋值了,啥也不是。
- 两个指针都向后移动一位,也就是比较第二三个数,如果这两个数重复,就比较二四数。
- 如果二四数不重复,
slow
指针向后移一位,第四项赋值给第三项,此时是[1, 2, 4, 4, 4, 5]
。 - 比较三五项,同样重复,单
fast
后移一位。 - 比较三六项,不重复,六项赋值四项。
[1, 2, 4, 5, 4, 5]
。 - 最后
slow
指向第四项,也就是index=3
,返回slow + 1
。
额,提交了一下,击败18.6%,还不如我自己写的那个呢。。。。。