文章目录
1. 青铜: leetcode-1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
虽然本题是青铜级,但是如果你写两层for循环时间复杂度为 O ( n 2 ) O(n^2) O(n2)的算法,也太说不过去了吧,估计只能算个废铁级。为了进入青铜级入门水平,我们可以用一个字典来存元素和下标,这样查找时间就为 O ( 1 ) O(1) O(1)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
num_index={}
for i in range(0,len(nums)):
num_index[nums[i]]=i
for i in range(0,len(nums)):
temp=target-nums[i]
if temp in num_index.keys() and i!=num_index[temp]:
return [i,num_index[temp]]
return []
2. 白银:2-sum问题变种之找出所有不重复的结果
给定一个整数数组 nums(里面没有重复元素) 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的所有的两个整数组合情况,并返回这样的整数组合对。
可以在上一节的答案基础上,循环遍历时把所有结果append到一个数组中。但是要注意判断元素是不是已经在之前出现过
class Solution:
def twoSum(self, nums, target: int):
results=[]
num_index={}
set_second_ele=set()
for i in range(0,len(nums)):
num_index[nums[i]]=i
for i in range(0,len(nums)):
temp=target-nums[i]
if temp in num_index.keys() and i!=num_index[temp] and not temp in set_second_ele:
results.append([nums[i],temp])
set_second_ele.add(nums[i])
return results
如果nums里面有重复元素咋办?只需要做一点小修改就行
class Solution:
def twoSum(self, nums, target: int):
results=[]
num_index={}
set_second_ele=set()
for i in range(0,len(nums)):
num_index[nums[i]]=i
for i in range(0,len(nums)):
temp=target-nums[i]
if temp in num_index.keys() and i!=num_index[temp] and not nums[i] in set_second_ele and not temp in set_second_ele:
results.append([nums[i],temp])
set_second_ele.add(nums[i])
return results
3. 黄金:leetcode-15. 三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
可以转化为2-sum问题,注意要去重。
class Solution:
def twoSum(self, nums, target: int, index_a: int,set_a,set_index_a):
results=[]
num_index={}
set_second_ele=set()
# set_first_ele=set()
for i in range(0,len(nums)):
num_index[nums[i]]=i
for i in range(index_a+1,len(nums)):
if i==index_a:
continue
temp=target-nums[i]
if temp in num_index.keys() and i<num_index[temp] and not temp in set_second_ele and nums[i] not in set_second_ele and num_index[temp]!=index_a and not i in set_index_a and not num_index[temp] in set_index_a:
results.append([nums[i],temp])
set_second_ele.add(nums[i])
# set_first_ele.add(nums[i])
return results
def threeSum(self, nums: List[int]) -> List[List[int]]:
results=[]
num_index={}
nums.sort()
for i in range(0,len(nums)):
num_index[nums[i]]=i
set_a=set()
set_index_a=set()
for index_a,a in enumerate(nums):
if a in set_a:
continue
two_sum_result=self.twoSum(nums,0-a,index_a,set_a,set_index_a)
set_a.add(a)
set_index_a.add(index_a)
for result in two_sum_result:
results.append([a]+result)
return results
还有一种更适合推广到k-sum的情况的算法,就先对数组排序,然后从低到高选择不重复的元素进行组合,检查是否满足要求:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
results=[]
nums.sort()
third_index_start=len(nums)-1
for first_index in range(0,len(nums)):
if first_index==0 or nums[first_index]!=nums[first_index-1]:
target1=-nums[first_index]
third_index=third_index_start
for second_index in range(first_index+1,len(nums)):
if second_index==first_index+1 or nums[second_index]!=nums[second_index-1]:
target2=target1-nums[second_index]
if target2>nums[third_index_start]:
continue
while third_index>second_index and target2<nums[third_index]:
third_index-=1
if third_index==second_index:
break
if target2==nums[third_index]:
results.append([nums[first_index],nums[second_index],nums[third_index]])
return results
4. 铂金:k数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在k个元素,并且这k个元素之和等于target ?请你找出所有这样的不重复的k元组。
注意:答案中不可以包含重复的k元组。
class Solution:
def recursive(self,start_index,current_cycle,target):
if current_cycle==self.total_cycle-1:
third_index=self.last_index#放到这里可减少一些操作
for second_index in range(start_index+1,self.n):
if second_index==start_index+1 or self.nums[second_index]!=self.nums[second_index-1]:
self.temp_result[current_cycle]=self.nums[second_index]
target2=target-self.nums[second_index]
if target2>self.nums[self.last_index]:
continue#剪枝
while third_index>second_index and target2<self.nums[third_index]:
third_index-=1
if third_index==second_index:
break#剪枝
if target2==self.nums[third_index]: self.temp_result[self.total_cycle]=self.nums[third_index]
self.results.append([ele for ele in self.temp_result])
return
else:
for first_index in range(start_index+1,self.n):
if first_index==start_index+1 or self.nums[first_index]!=self.nums[first_index-1]:
self.temp_result[current_cycle]=self.nums[first_index]
target1=target-self.nums[first_index] self.recursive(first_index,current_cycle+1,target1)
def kSum(self, nums: List[int], target: int, k: int) -> List[List[int]]:
nums.sort()
self.nums=nums
self.n=len(nums)
self.last_index=self.n-1
self.results=[]
self.total_cycle=k-1
self.temp_result=[0]*(self.total_cycle+1)
start_index=-1
current_cycle=0
#print(self.nums)
self.recursive(start_index,current_cycle,target)
return self.results
5. 钻石:最接近的k数之和
给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出k个整数,使它们的和与 target 最接近。
返回这k个数的和。
假定每组输入只存在恰好一个解。
本题的实际例子就是leetcode 16. 最接近的三数之和
解法是基于第4章之上的,区别在于需要动态更新k数之和与target的差(注意要取绝对值),以及对应地更新k数之和。最终选择最接近k数之和作为result
class Solution:
def recursive(self,start_index,current_cycle,target):
if current_cycle==self.total_cycle-1:
for second_index in range(start_index+1,self.n):
if second_index==start_index+1 or self.nums[second_index]!=self.nums[second_index-1]:
third_index=self.last_index#注意不能放到前面了,必须放在这里,因为没有剪枝操作,需要完成second_index的循环。每轮迭代需要将third_index重置
target2=target-self.nums[second_index]
while third_index>second_index:
cur_dev=target2-self.nums[third_index]
if abs(cur_dev)<self.deviation:
self.deviation=abs(cur_dev)
self.result=self.target-cur_dev
third_index-=1
return
else:
for first_index in range(start_index+1,self.n):
if first_index==start_index+1 or self.nums[first_index]!=self.nums[first_index-1]:
target1=target-self.nums[first_index]
self.recursive(first_index,current_cycle+1,target1)
def threeSumClosest(self, nums: List[int], target: int) -> int:
self.deviation=99999999
self.target=target
nums.sort()
self.nums=nums
print(nums)
self.n=len(nums)
self.last_index=self.n-1
self.result=0
self.total_cycle=3-1
start_index=-1
current_cycle=0
self.recursive(start_index,current_cycle,self.target)
return self.result