题号1:两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
- 法一
这题最简单的办法无非就是暴力解法,两个循环就解决,时间复杂度是O(n2)。太过简单,我也懒得贴代码了。
- 法二
双指针法:L指针指向数组头部,R指针指向数组尾部。
L+R==Target时,直接返回
L+R<Target时,L指针左移
L+R>Target时,R指针右移
这种方法的时间复杂度为O(n)
class Solution:
def twoSum(self, nums: 'List[int]', target: 'int') -> 'List[int]':
l=0
r=len(nums)-1
while(l<r):
if nums[l]+nums[r]==target:
return [l,r]
elif nums[l]+nums[r]<target:
l+=1
else:
r-=1
但是请注意:这种方法只能在数组已经排序好的情况下使用,要AC这题的话,我们最好还是换种方法
- 法三
字典法,时间复杂度同样为O(n)。创建一个空字典。对数组进行遍历,若Target减去当前项存在于字典中,通过key获得value,直接返回[value和当前项即可]。若不存在,把当前项存入字典中
废话少说,上代码
class Solution:
def twoSum(self, nums: 'List[int]', target: 'int') -> 'List[int]':
dic={}
for index, value in enumerate(nums):
want=target-value
if want in dic:
return [dic[want],index]
else:
dic[value]=index
return []
题号15:三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0
找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
- 使用上一题的双指针法即可解,代码如下
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
triple=[]
nums.sort()
for i in range(len(nums)-2):
j=i+1
k=len(nums)-1
while(j<k):
if nums[j]+nums[k]+nums[i]==0:
a=[nums[i],nums[j],nums[k]]
if a not in triple:
triple.append(a)
j+=1
elif nums[j]+nums[k]+nums[i]<0:
j+=1
else:
k-=1
return triple
时间复杂度为O(n2),虽然一遍ac了但是达到了8300ms仅击败零点几的用户,很蛋疼啊,一定有更好的办法
对其进行改进,代码如下
class Solution:
def threeSum(self, nums: 'List[int]') -> 'List[List[int]]':
target=0
dic={}
triple=[]
if len(nums)<3:
return []
for i in nums:
if i in dic:
dic[i] += 1
else:
dic[i] = 1
nums=[i for i in dic]
nums.sort()
if target%3==0:
if int(target/3)in dic:
if dic[int(target/3)]>2:
fuck=int(target/3)
triple.append([fuck,fuck,fuck])
for i in range(len(nums)):
j=i+1
k=len(nums)-1
want=target-nums[i]
if want%2==0 and nums[i]!=int(want/2):
if int(want/2) in dic:
if dic[int(want/2)]>1:
a=[nums[i],int(want/2),int(want/2)]
a.sort()
triple.append(a)
while(j<k):
if nums[j]+nums[k]==want:
triple.append([nums[i],nums[j],nums[k]])
j+=1
elif nums[j]+nums[k]<want:
j+=1
elif nums[j]+nums[k]>want:
k-=1
return triple
优化至1300ms,好过百分之三十四的同学,一定还有更好的办法,再次优化如下
class Solution:
def threeSum(self, nums: 'List[int]') -> 'List[List[int]]':
dic={}
triple=[]
for i in nums:
if i in dic:
dic[i] += 1
else:
dic[i] = 1
pos = [i for i in dic if i>0]
neg = [i for i in dic if i<0]
if 0 in dic and dic[0]>2:
triple.append([0,0,0])
for i in neg:
for j in pos:
want=-i-j
if want in dic:
if (want==i or want==j) and dic[want]>1:
triple.append([i,want,j])
elif i<want<j:
triple.append([i,want,j])
return triple
击败了98.37的用户,应该极限就在这里了。
题号16:最接近的三数之和解法类似,不赘述
题号18:四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a +
b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。注意:
答案中不可以包含重复的四元组。
示例:给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
其实把上题的代码稍作修改即可ac,如下:
class Solution:
def threeSum(self, nums: 'List[int]',target:'int') -> 'List[List[int]]':
dic={}
triple=[]
if len(nums)<3:
return []
for i in nums:
if i in dic:
dic[i] += 1
else:
dic[i] = 1
nums=[i for i in dic]
nums.sort()
if target%3==0:
if int(target/3)in dic:
if dic[int(target/3)]>2:
fuck=int(target/3)
triple.append([fuck,fuck,fuck])
for i in range(len(nums)):
j=i+1
k=len(nums)-1
want=target-nums[i]
if want%2==0 and nums[i]!=int(want/2):
if int(want/2) in dic:
if dic[int(want/2)]>1:
a=[nums[i],int(want/2),int(want/2)]
a.sort()
triple.append(a)
while(j<k):
if nums[j]+nums[k]==want:
triple.append([nums[i],nums[j],nums[k]])
j+=1
elif nums[j]+nums[k]<want:
j+=1
elif nums[j]+nums[k]>want:
k-=1
return triple
def fourSum(self, nums: 'List[int]', target: 'int') -> 'List[List[int]]':
if len(nums)<4:
return []
nums.sort()
joke=[]
i=0
while(i<len(nums)-1):
#print(nums[i+1:])
tree= self.threeSum(nums[i+1:],target-nums[i])
for k in tree:
new=[nums[i]]
new+=k
joke.append(new)
while(nums[i]==nums[i+1] and i+1<len(nums)-1):
i+=1
i+=1
return joke
仅击败10.98的用户,当然可以再优化,但是这和前几题的原理基本相同,懒得弄了。就到这吧