代码随想录算法训练营第六天|454.四数相加II,383. 赎金信,15. 三数之和,18. 四数之和,总结

系列文章目录

代码随想录算法训练营第一天|数组理论基础,704. 二分查找,27. 移除元素
代码随想录算法训练营第二天|977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
代码随想录算法训练营第三天|链表理论基础,203.移除链表元素,707.设计链表,206.反转链表
代码随想录算法训练营第四天|24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面试题 02.07. 链表相交,142.环形链表II,总结
代码随想录算法训练营第五天|哈希表理论基础,242.有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和

文章目录

  • 系列文章目录
  • 454.四数相加II
  • 383. 赎金信
  • 15. 三数之和
  • 18. 四数之和
  • 总结


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
视频讲解:学透哈希表,map使用有技巧!LeetCode:454.四数相加II

核心思路:
先遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到字典中,然后遍历大C和大D数组,统计0-(c+d) 在dict中出现的情况。

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        record=dict()
        for i in range(len(nums1)):
            for j in range(len(nums2)):
                record[nums1[i]+nums2[j]]=record.get(nums1[i]+nums2[j],0)+1
        count=0
        for i in range(len(nums3)):
            for j in range(len(nums4)):
                target=nums3[i]+nums4[j]
                if 0-target in record:
                    count+=record[0-target]
        return count

383. 赎金信

题目链接: 383.赎金信
题目内容: 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 false 。magazine 中的每个字符只能在 ransomNote 中使用一次

使用数组:

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        ransomNote_count=[0]*26
        magazine_count=[0]*26
        for i in ransomNote:
            ransomNote_count[ord(i)-ord('a')]+=1
        for i in magazine:
            magazine_count[ord(i)-ord('a')]+=1
        return all(ransomNote_count[i]<=magazine_count[i] for i in range(26))

使用字典:

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        record={}
        for i in magazine:
            record[i]=record.get(i,0)+1
        for i in ransomNote:
            if i not in record or record[i] == 0:
                return False
            record[i]-=1
        return True

15. 三数之和

题目链接: 15.三数之和
题目内容: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。
视频讲解:梦破碎的地方!| LeetCode:15.三数之和

哈希法:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        result = []
        nums.sort()
        # 找出a + b + c = 0
        # a = nums[i], b = nums[j], c = -(a + b)
        for i in range(len(nums)):
            # 排序之后如果第一个元素已经大于零,那么不可能凑成三元组
            if nums[i] > 0:
                break
            if i > 0 and nums[i] == nums[i - 1]: #三元组元素a去重
                continue
            d = {}
            for j in range(i + 1, len(nums)):
                if j > i + 2 and nums[j] == nums[j-1] == nums[j-2]: # 三元组元素b去重
                    continue
                c = 0 - (nums[i] + nums[j])
                if c in d:
                    result.append([nums[i], nums[j], c])
                    d.pop(c) # 三元组元素c去重
                else:
                    d[nums[j]] = j
        return result

双指针法:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        result=[]
        for i in range(len(nums)):
            if nums[i] > 0: 
                return result
            if i > 0 and nums[i] == nums[i-1]:
                continue
            left=i+1
            right=len(nums)-1
            while left<right:
                if nums[left]+nums[right]+nums[i]>0:
                    right-=1
                elif nums[left]+nums[right]+nums[i]<0:
                    left+=1
                else:
                    result.append([nums[i],nums[left],nums[right]])
                    while right>left and nums[right]==nums[right-1]:
                        right-=1
                    while right>left and nums[left]==nums[left+1]:
                        left+=1
                    left+=1
                    right-=1
        return result

18. 四数之和

题目链接: 18.四数之和
题目内容: 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):0 <= a, b, c, d < n;a、b、c 和 d 互不相同;nums[a] + nums[b] + nums[c] + nums[d] == target;你可以按 任意顺序 返回答案 。
视频讲解:难在去重和剪枝!| LeetCode:18. 四数之和

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        n = len(nums)
        result = []
        for i in range(n):
            if nums[i] > target and nums[i] > 0 and target > 0:# 剪枝(可省)
                break
            if i > 0 and nums[i] == nums[i-1]:# 去重
                continue
            for j in range(i+1, n):
                if nums[i] + nums[j] > target and target > 0: #剪枝(可省)
                    break
                if j > i+1 and nums[j] == nums[j-1]: # 去重
                    continue
                left, right = j+1, n-1
                while left < right:
                    s = nums[i] + nums[j] + nums[left] + nums[right]
                    if s == target:
                        result.append([nums[i], nums[j], nums[left], nums[right]])
                        while left < right and nums[left] == nums[left+1]:
                            left += 1
                        while left < right and nums[right] == nums[right-1]:
                            right -= 1
                        left += 1
                        right -= 1
                    elif s < target:
                        left += 1
                    else:
                        right -= 1
        return result

总结

  1. 一般来说哈希表都是用来快速判断一个元素是否出现集合里;
  2. 使用哈希法解决问题时,一般会选择如下三种数据结构:数组、set (集合)、map(映射):
    • 数组:哈希值比较小,范围也比较小
    • set:数值比较大
    • map:key,value

你可能感兴趣的:(力扣算法刷题,算法,python,力扣)