官方解法:
双重指针
def removeDuplicates(self, nums):
if len(nums)==0:#要对空数组做处理
return 0
i=0
for j in range(len(nums)):#他用一个循环就解决了,主要是对j的遍历,i看情况+1就行了
if nums[i]!=nums[j]:
i=i+1
nums[i]=nums[j]
j=j+1
return i+1
我的想法:
1.在每个位置挨着试序号,有则交换。然后下一个位置从刚刚的数字+1试起
def removeDuplicates(self, nums):
count=0
while True:
for j in range(len(nums)):
for i in range(len(nums)):
if nums[i]==count:
temp=nums[i]
nums[i]=nums[j]
nums[j]=temp
break
count=count+1
2.堆的方式。先找最小的放第一个(交换),然后找第二小的。temp存
class Solution(object):
def removeDuplicates(self, nums):
min1=nums[0]
p=0
for i in range(len(nums)):#找第一个最小值
if nums[i]<min1:
min1=nums[i]
min2=min1+1
temp=nums[i]
nums[i]=nums[0]
nums[0]=temp
while min1<min2:
for i in range(len(nums)):#找当前最小值
if nums[i]<min2:
min2=nums[i]
temp=nums[i]
nums[i]=nums[0]
nums[0]=temp
min1=min2
min2=min1+1
看解答后:
def removeDuplicates(self, nums):
i=0
j=0
while j<len(nums):
while j<len(nums) and nums[i]==nums[j]:
j=j+1
if j !=len(nums) and j-i>1:#添加一个小判断,当 j-i>1时,即无重复时才进行复制
nums[i+1]=nums[j]#若无if,i+1会溢出 ,因为当i,j都走到最后,上面的while未执行,再执行这一步就会出错。
i=i+1
return i+1 #返回长度,i+1
题27:
我思路:前后各一个指针i,j,将非val换到前面
(1)若i向后搜到val,j要从后向前搜一个非val的元素,交换
(2)若j遇到val,跳过
(3)j后全为val,i前全为非val,
(4)当i,j相遇,说明结束.此时要判断相遇处为val,以返回长度i
def removeElement(self, nums, val):
if len(nums)==0:
return 0
i=0
j=len(nums)-1
for i in range(len(nums)):
if nums[i]==val:#搜到了才考虑交换,否则直接往后走
while j!=i and nums[j]==val:
j=j-1
#对终止条件进行判断
if j!=i:#说明找到了可交换的元素
temp=nums[i]
nums[i]=nums[j]
nums[j]=temp
# j=j-1 错,不能让j主动往前走,否则相遇元素可能不是val
else:
return i
耶!第一次自己提交过,而且是一遍过。调试也就一次不对,而且自己很快就看出了错误
优化:(其实可以不交换,直接覆盖就行了)
(1)若i向后搜到val,j要从后向前搜一个非val的元素,覆盖
(2)若j遇到val,跳过
(3)j后仍有非val
(4)当i,j相遇(对i,j的行动都要判断),说明结束.此时要判断相遇处为val,以返回长度i
class Solution(object):
def removeElement(self, nums, val):
if len(nums)==0:
return 0
if len(nums)==1 and nums[0]==val:#若【1】1,即i,j本来就相等,根据下面会返回i+1,所以要特殊处理
return 0
i=0
j=len(nums)-1
for i in range(len(nums)):
if i==j:#若采用交换,j后都是val,所以当i先遍历时,就算穿过j,也会停下来,等j找可交换的,而此时他们正好相等,所以算法结束
#而本算法采用的是覆盖,j后的非val值仍然存在,当i先遍历找val,完全可能穿过j,把所有元素都修改
return i if nums[i]==val else i+1
if nums[i]==val:#搜到了才考虑交换,否则直接往后走
while j!=i and nums[j]==val: #有bug,若j向前压根没搜到可用来覆盖的元素,但是与i相遇了,此时指向的就是val,所以要判断
j=j-1
#对终止条件进行判断
if j!=i:#说明找到了可覆盖的元素
nums[i]=nums[j]
j=j-1 #此时必须让j主动往前走,否则永远在用一个元素覆盖前面的值#这时是j先指向可以用来覆盖的元素,再是i找到需要覆盖的val
#那最后相遇就是j主动的,因为他没有找到可以用来覆盖的,所以相遇处值是非val
if j==i: #在上句中,j又走了,所以也要判断
return i if nums[i]==val else i+1
官方解法:
1.快慢指针:
快指针j遍历一次所有元素,忽略val,只看实际要装入数组的元素
慢指针指示被装入的位置
这种方法每个位置都要重新填,但未更改元素顺序
def removeElement(self, nums, val):
if len(nums)==0:
return 0
i=0
j=0
for j in range(len(nums)):
if nums[j]!=val:
nums[i]=nums[j] #直接覆盖就行了,不用担心,j已经把所有元素遍历了,该保存的已经移到前面了
i=i+1 #nums[j]!=val时,即替换时才移到,所以更慢
return i