N数之和的主要思想就是双指针,首先保证数组是排序数组,然后设置双指针left和right,不断比较left和right所指的元素和是否是target。
代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
num = sorted(nums) #sorted()可以保证原数组不变,sort()会改变原数组
left = 0
right = len(num) - 1
answer = []
while left < right:
sum_num = num[left] + num[right]
if sum_num < target:
left += 1
if sum_num > target:
right -= 1
if sum_num == target:
if num[left] != num[right]: #两个数不相等时,用index找下标即可
answer = [nums.index(num[left]),nums.index(num[right])]
else:
answer = [i[0] for i in list(enumerate(nums)) if i[1] == num[left]] #两个数相等时,用enumerate()找到全部的下标元素
break
return answer
三数之和就用两个循环,外层循环就对三数中的一个数进行遍历,内循环就遍历该数之外的数组。同样要求数组是排序数组。
代码如下:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
i = 0
num = sorted(nums)
answer = []
while i < len(num): #外层循环
target = 0 - num[i] #设置target
right = len(num) - 1
left = i + 1
while left < right: #内层循环
sum_two = num[left] + num[right]
if sum_two < target:
left += 1
if sum_two > target:
right -= 1
if sum_two == target:
if [num[i], num[right], num[left]] not in answer: #保证了后面的数不会和前面的重复
answer.append([num[i], num[right], num[left]])
left += 1
right -= 1
i += 1
return answer
按照上面三数之和的思路,遍历其中一个数字,然后调用三数之和。
class Solution:
def treeSum(self,num,target1):
i = 0
answer = []
while i < len(num):
target = target1 - num[i]
right = len(num) - 1
left = i + 1
while left < right:
sum_two = num[left] + num[right]
if sum_two < target:
left += 1
if sum_two > target:
right -= 1
if sum_two == target:
if [num[i], num[right], num[left]] not in answer:
answer.append([num[i], num[left], num[right]])
left += 1
right -= 1
i += 1
return answer
def fourSum(self, nums, target):
i = 0
nums.sort() #先排序
answer = []
while i < len(nums):
target1 = target - nums[i]
num = nums[i+1:] #将剩余的数组传入三数之和的函数中
anw = self.treeSum(num,target1)
if len(anw): #如果能找到这个三数之和
for a in anw:
a.insert(0,nums[i]) #将第四个数插入到结果中
if a not in answer: #确保不会出现重复元素
answer.append(a)
i += 1
return answer
总结:Nsum问题都是遍历其中一个数,然后递归到两数之和,两数之和用双指针和排序解决。