leetcode 454.四数相加II
题目
454.四数相加II
给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
解题思路
1、四个数组分成两组,nums1和nums2为一组(A组),nums3和nums4为一组(B组) --两层for循环分别计算出A、B的值
2、原题目转换为A组和B组的元素和为0,和题目1.两数之和类似 --判断0减去B的值是否在A中(判断元素是否出现用哈希法)
3、计算满足A + B = 0 有多少个元祖,即除了求满足条件的值之外,还要统计值的个数 --满足条件的值为key,值的个数为value(哈希法的数据结构使用字典)
实现代码
from typing import List
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
hashmap = dict() # key存值,value存值出现的次数
for n1 in nums1:
for n2 in nums2:
a = n1 + n2
print('a=', a)
hashmap[a] = hashmap.get(a, 0) + 1 # 在字典中取key为a的值,如果没有返回0,有就+1
# print(hashmap)
count = 0
for n3 in nums3:
for n4 in nums4:
b = n3 + n4
target = 0 - b
# print('target=', target)
if target in hashmap:
count += hashmap[target]
return count
test = Solution()
nums1 = [1,2]
nums2 = [-2,-1]
nums3 = [-1,2]
nums4 = [0,2]
print(test.fourSumCount(nums1, nums2, nums3, nums4))
leetcode 383. 赎金信
题目
383. 赎金信
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
解题思路
判断ransomNote中的元素是否都能在magazine中找到 --哈希法
该题目和242.有效字母异位词一样的解法
实现代码
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
arr = [0] * 26
for i in ransomNote:
arr[ord(i) - ord('a')] += 1
for i in magazine:
arr[ord(i) - ord('a')] -= 1
# for i in range(26): # ransomNote = 'fihjjjjei', magazine = 'hjibagacbhadfaefdjaeaebgi' 用例执行失败
# if arr[i] <= 0:
# return True
# else:
# return False
# all()函数:判断给定的可迭代参数iterable中的所有元素是否都为TRUE,如果是返回True,否则返回 False。元素除了是0、空、None、False外都算True。
return all(arr[i] <= 0 for i in range(26)) # ransomNote = 'fihjjjjei', magazine = 'hjibagacbhadfaefdjaeaebgi' 用例执行成功
test = Solution()
# ransomNote = "aab"
# magazine = "bc"
# ransomNote = 'ab'
# magazine = 'ab'
# ransomNote = "a"
# magazine = "b"
ransomNote = 'fihjjjjei' # 1个f,2个i,1个h,4个j,1个e
magazine = 'hjibagacbhadfaefdjaeaebgi' # 2个f,2个i,1个h,2个j,3个e
print(test.canConstruct(ransomNote, magazine))
leetcode 15. 三数之和
题目
15. 三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。
解题思路
双指针 + 去重
1、双指针法遍历出所有和为0的三元组
(1)对数组进行排序
(2)for循环遍历数组,i从下标为0的位置开始
(3)定义双指针left和right,left位置为i+1,right位置为数组末尾位len(nums)-1
(4)三元组的和s = nums[i] + nums[left] + nums[right]
(5)通过判断三元组的和来移动双指针
如果s>0,三元组和需要变小,right指针向左移动,right -= 1
如果s<0,三元组的和需要变大,left指针向右移动,left += 1
如果s=0,三元组的和为0,得到结果,将nums[i],nums[left],num[right]添加到数组中,然后继续遍历i,left右移,right左移,直到left与right相遇
2、去掉重复的三元组(注意:是三元组不重复,三元组中的元素是可以重复的)
(1)判断nums[i]和它的前一位nums[i-1]是否重复,如果重复说明值已经在三元组中使用过,所以跳过nums[i]和其对应的三元组结果,继续向后找
(2)判断nums[left+1]和它的前一位num[left]是否重复,如果重复,left继续向右移动 left+=1
(3)判断nums[right-1]和它的后一位nums[right]是否重复,如果重复,right继续向左移动 right-=1
实现代码
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort() # 排序
res = []
for i in range(len(nums)):
if nums[i] > 0: # 排序后如果第一个值都大于0,则直接返回空数组
return res
# nums[i]去重
if i > 0 and nums[i] == nums[i -1]: # 如果nums[i]和它的前一位nums[i-1]相等,则要跳过nums[i],i继续向右移动
continue
left = i + 1
right = len(nums) - 1
while left < right:
s = nums[i] + nums[left] + nums[right]
if s < 0:
left += 1
elif s > 0:
right -= 1
else:
res.append([nums[i], nums[left], nums[right]])
# nums[right]去重
while right > left and nums[right] == nums[right-1]:
right -= 1
# nums[left]去重
while right > left and nums[left] == nums[left+1]:
left += 1
right -= 1
left += 1
return res
test = Solution()
nums = [-1,0,1,2,-1,-4]
print(test.threeSum(nums))
leetcode 18. 四数之和
题目
解题思路
实现代码