1. 两数之和
- 暴力解法
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
for j in range(i+1,len(nums)):
if nums[i] + nums[j] == target:
return [i, j]
- 判断
target - num[i]
是否在nums中并且不是num[i], 不是就用index()
函数找到其位置
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
for i in range(len(nums)):
if (target-nums[i]) in nums:
j = nums.index(target-nums[i])
if i!=j:
return [i, j]
else:
continue
- 在num[i]之前定位j
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
j = -1
for i in range(1,len(nums)):
temp_nums = nums[:i]
if (target-nums[i]) in temp_nums:
j = temp_nums.index(target-nums[i])
break
if j>=0:
return [i, j]
- 在num[i]之后定位,效果不如解法3
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
j = -1
for i in range(0,len(nums)-1):
temp_nums = nums[i+1:]
if (target-nums[i]) in temp_nums:
j = temp_nums.index(target-nums[i]) + i + 1
break
if j>=0:
return [i, j]
- 在hash的num之前进行查找,为什么会有人想到这么机智的办法
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
# hash dict
hash = {}
# 仅在num[i]之前的dict中查找
for i,num in enumerate(nums):
if hash.get(target - num) is not None:
return [i, hash.get(target-num)]
hash[num] = i
15. 三数之和
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
# 固定K位置,移动ij
ans = []
nums.sort()
for k in range(len(nums)-2):
i, j = k+1, len(nums) - 1 # i,j的初始位置是k后片段的两个极端点
if nums[k] > 0: break
if k > 0 and nums[k] == nums[k-1] : continue # 跳过重复的K
while i < j: # i不断前移,j不断后移,直到相遇跳出循环, i!=j 不对
s = nums[i] + nums[j] + nums[k]
if s > 0:
j -= 1
while i < j and nums[j] == nums[j+1]: j -= 1 # 在i<j的前提下,不断往左倒退直到和现在的j不相等为止
elif s < 0:
i += 1
while i < j and nums[i] == nums[i-1]: i += 1 # 在i<j的前提下,不断往右前进直到和现在的i不相等为止
else:
ans.append([nums[k], nums[i], nums[j]])
# i j 还需要继续走 可能有其他i j 组合和k=0
i += 1
while i < j and nums[i] == nums[i - 1]: i += 1 # 在i<j的前提下,不断往右前进直到和现在的i不相等为止
j -= 1
while i < j and nums[j] == nums[j + 1]: j -= 1 # 在i<j的前提下,不断往左倒退直到和现在的j不相等为止
return ans
16. 最接近的三数之和
定义一个最小差值,每次计算出一个差值后和最小差值的绝对值比较,取更小的差值,如果差值=0直接return target,否则return最小差值和target的和
class Solution(object):
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums.sort()
# 设置一个最接近和和次接近和,i,j朝着更接近target的方向走
mincha = nums[0] + nums[1] + nums[2] - target
for k in range(len(nums) - 2):
i, j = k + 1, len(nums) - 1
if k > 0 and nums[k] == nums[k - 1]: continue
while i < j:
cha = nums[i] + nums[j] + nums[k] - target
# cha < 0 增加i cha > 0 减小j cha = 0 break
if cha < 0:
i += 1
while i < j and nums[i-1] == nums[i] : i += 1
elif cha > 0:
j -= 1
while i < j and nums[j+1] == nums[j] : j -= 1
else:
return target
if abs(cha) < abs(mincha):
mincha = cha
return mincha + target
可以说是贼开心了!
18. 四数之和
和三数之和的区别是需要用双循环固定前两个数,以及这道题可以有重复元素出现,所以不需要while跳重复数字,set()可以add()进一个元组,
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
nums.sort()
n = len(nums)
ans = set()
# 固定前两个数,后两个数一左一右地移动
for i in range(0, n-3):
for j in range(i+1, n-2):
k, l = j + 1, n - 1
while k < l:
temp = nums[i] + nums[j] + nums[k] + nums[l]
if temp < target:
k += 1
elif temp > target:
l -= 1
else:
ans.add((nums[i], nums[j], nums[k], nums[l])) # set() .add()可以添加一个元组
k += 1
l -= 1
res = []
for a in ans:
res.append(list(a))
return res
454. 四数相加II
Counter()是计算可迭代对象每种元素出现的个数
class Solution(object):
def fourSumCount(self, A, B, C, D):
"""
:type A: List[int]
:type B: List[int]
:type C: List[int]
:type D: List[int]
:rtype: int
"""
# 先计算a+b的和的字典
from collections import Counter
dict = Counter(a+b for a in A for b in B)
# 在字典中找-c-d的值,有多少个说明有多少个配对的四元组
return sum(dict.get(-c-d, 0) for c in C for d in D)