目录
- 454.四数相加II
- [383. 赎金信](#383. 赎金信)
- [15. 三数之和](#15. 三数之和)
- [18. 四数之和](#18. 四数之和)
454.四数相加II
题目链接: 454.四数相加II - 力扣(LeetCode)
文章讲解:代码随想录
思路
- 暴力解,超时,时间复杂度为n^4
- 利用字典类哈希表优化为n^2
暴力解【超时】
python
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
hash1 = []
for num1 in nums1:
for num2 in nums2:
hash1.append(num1+num2)
hash2 = []
for num3 in nums3:
for num4 in nums4:
hash2.append(num3+num4)
count = 0
for i in hash1:
for j in hash2:
if i+j == 0:
count += 1
return count
字典类哈希表
python
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
hash1 = collections.defaultdict(int)
for num1 in nums1:
for num2 in nums2:
hash1[num1+num2] += 1
count = 0
for num3 in nums3:
for num4 in nums4:
if -(num3+num4) in hash1:
count += hash1[-(num3+num4)]
return count
383. 赎金信
题目链接: 383. 赎金信 - 力扣(LeetCode)
文章讲解:代码随想录
思路
- 类似 242.有效的字母异位词,用哈希表解决
- 利用python内置的Counter类优化
哈希表
python
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
hashtable = collections.defaultdict(int)
for i in magazine:
hashtable[i] += 1
for j in ransomNote:
hashtable[j] -= 1
for k in hashtable.values():
if k < 0 :
return False
return True
Counter类
python
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
return collections.Counter(ransomNote) <= collections.Counter(magazine)
15. 三数之和
题目链接: 15. 三数之和- 力扣(LeetCode)
文章讲解:代码随想录
思路
- 暴力解,超时
- 将nums变成有序序列,固定第一个数,变成两数之和问题,使用相向双指针确定另外两个数【根据题意,需要注意去除重复答案】
- 进一步优化和剪枝
暴力解【超时】
python
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
l = []
for i in range(len(nums)-2):
for j in range(i+1,len(nums)-1):
for k in range(j+1,len(nums)):
if nums[i] + nums[j] + nums[k] == 0:
ll = [nums[i] , nums[j] , nums[k]]
ll.sort()
if ll not in l:
l.append(ll)
return l
遍历+左右指针
python
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
n = len(nums)
l = []
for i in range(n-2):
if(i>0 and nums[i]==nums[i-1]):# 重复,就跳过这个值
continue
left = i+1
right = n-1
while left<right:
if nums[i]+nums[left]+nums[right] == 0:
l.append([nums[i],nums[left],nums[right]])
left = left+1
while(left<right and nums[left]==nums[left+1]):#去重
left=left+1
right = right-1
while(left<right and nums[right]==nums[right-1]):#去重
right=right-1
elif nums[i]+nums[left]+nums[right] < 0:
left = left+1
else:
right = right-1
return l
进一步优化
python
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
# 优化3
if(not nums or n<3):
return []
nums.sort()
l = []
for i in range(n-2):
if(i>0 and nums[i]==nums[i-1]):#去重
continue
# 优化1:nums[i]和其他最小的两个数相加>0,则之后的情况全部都>0,break
if nums[i]+nums[i+1]+nums[i+2]>0:
break
# 优化2:nums[i]和其他最大的两个数相加<0,则本循环的其他情况都<0,continue
if nums[i]+nums[-1]+nums[-2]<0:
continue
left = i+1
right = n-1
while left<right:
if nums[i]+nums[left]+nums[right] == 0:
l.append([nums[i],nums[left],nums[right]])
left = left+1
while(left<right and nums[left]==nums[left+1]):#去重
left=left+1
right = right-1
while(left<right and nums[right]==nums[right-1]):#去重
right=right-1
elif nums[i]+nums[left]+nums[right] < 0:
left = left+1
else:
right = right-1
return l
18. 四数之和
题目链接: 18. 四数之和 - 力扣(LeetCode)
文章讲解:代码随想录
思路
- 三数之和升级,解法一样
方法
python
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
n = len(nums)
if n < 4:
return[]
nums.sort()
l = []
for i in range(n-3):
if i>0 and nums[i] == nums[i-1]:
continue
for j in range(i+1,n-2):
if j>i+1 and nums[j] == nums[j-1]:
continue
value = target-nums[i]-nums[j]
left = j+1
right = n-1
while left<right:
if nums[left] + nums[right] > value:
right -= 1
elif nums[left] + nums[right] < value:
left += 1
else:
l.append([nums[i], nums[j], nums[left], nums[right]])
left += 1
while left<right and nums[left] == nums[left-1]:
left += 1
right -= 1
while left<right and nums[right] == nums[right+1]:
right -= 1
return l