关于本次数组的练习题,主要包含了去除重复元素、去除特定元素的两个子问题(esp.去重)。对于该问题,可以根据是否使用额外存储空间分为两类:
1.使用额外存储空间
① 可以使用set()辅助去重,但要注意,集合中元素的数据类型虽然可以不同,但必须都是不可变类型,不能是列表、元组、集合、字典等(见第三题中的第一种错法);
②可以将需要删去的(即在上一步检测出重复的地方)序号存储到一个列表里,将列表去重并反转(或反向排序),再迭代删去(反转非常重要,因为如果不反转则会在删除的过程中出现序号的改变,从而导致溢出)
2.不使用额外存储空间
①不可以排序后直接迭代删除,因为这样会导致溢出(大家也有在群里探讨过);
②使用排序+双指针方法,通常是fast和slow指针(其根本在于在数组内原地修改,因此我对于第二题使用的那种解法也是对此进行了一定程度借鉴的。)
T1.删除有序数组中的重复项
#(排序+)双指针
class Solution(object):
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
fast=slow=1
while fast<len(nums):
if nums[fast]!=nums[fast-1]:
nums[slow]=nums[fast]
slow+=1
fast+=1
nums=nums[:slow]
return len(nums)
T2.移除元素
#排序式原地修改
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
if not nums:
return 0
m=max(nums)+1
count=0
for i in range(len(nums)):
if nums[i]==val:
nums[i]=m
count+=1
nums.sort()
nums=nums[:len(nums)-count]
return len(nums)
对于此题,也可以使用排序+双指针的常规方法。
T3.三数之和
#TypeError: unhashable type: 'list'
#集合中元素的数据类型虽然可以不同,但必须都是不可变类型,不能是列表、元组、集合、字典等
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
b=[]
l=len(nums)
for i in range(l):
for j in range(i,l):
for k in range(j,l):
if nums[i]+nums[j]+nums[k]==0:
a=[nums[i]]
a.append(nums[j])
a.append(nums[k])
b.append(a)
the_set=set(b)
c=list(the_set)
return c
#忘记了双指针前必须排序,而这种数据类型无法排序,因此行不通
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
b=[]
l=len(nums)
for i in range(l):
for j in range(i,l):
for k in range(j,l):
if nums[i]+nums[j]+nums[k]==0:
a=[nums[i]]
a.append(nums[j])
a.append(nums[k])
b.append(a)
fast=slow=1
while fast<len(b):
if set(b[fast])!=set(b[fast-1]): #不过这里想法其实还挺正确的
b[slow]=b[fast]
slow+=1
fast+=1
b=b[:slow]
return b
#暴力解法(不过超时了)
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
b=[]
l=len(nums)
for i in range(l):
for j in range(i+1,l):
for k in range(j+1,l):
if nums[i]+nums[j]+nums[k]==0:
a=[nums[i]]
a.append(nums[j])
a.append(nums[k])
b.append(a)
c=[]
for x in range(len(b)):
for y in range(x+1,len(b)):
if set(b[x])==set(b[y]):
c.append(x)
#这两部用来解决前面几句代码的不完善之处,将列表去重并反转(或反向排序),再迭代删去(反转非常重要,因为如果不反转则会在删除的过程中出现序号的改变,从而导致溢出)
c=list(set(c))
c.sort(reverse=True) #避免栈溢出
if c!=[]:
for m in c:
del b[m]
return b
#排序+双指针
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
ans=list()
nums.sort()
l=len(nums)
for first in range(l):
if first>0 and nums[first]==nums[first-1]:
continue
target=-nums[first]
third=l-1
for second in range(first+1,l):
if second>first+1 and nums[second]==nums[second-1]:
continue
while second<third and nums[second]+nums[third]>target:
third-=1
if second==third:
break
if nums[second]+nums[third]==target:
ans.append([nums[first],nums[second],nums[third]])
return ans
末尾mark一篇讲解双指针的博客:https://blog.csdn.net/thekingspath/article/details/110572143?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164493965116781685342606%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164493965116781685342606&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-110572143.pc_search_result_positive&utm_term=python%E5%8F%8C%E6%8C%87%E9%92%88&spm=1018.2226.3001.4187