代码随想录算法训练营day07 | 454.四数相加II 、383. 赎金信 、15. 三数之和 、18. 四数之和

哈希表part02(24.01.02)

安排:先独立做题,然后看视频讲解,然后看文章讲解,然后再重新做一遍题,把题目AC,最后整理成今日当天的博客。


学习时长:三个半小时
学习内容:自己尝试+pdf说明+视频+力扣题解+自己默写
学习感悟:渐入佳境!


454.四数相加II 

题目链接:力扣题目链接

笔记:

        1.四个数组两两分组,分别进行元素遍历加和(大A和大B,大C和大D)key放a和b两数之和,value 放a和b两数之和出现的次数。将和以及次数放入哈希表,在对C和D遍历时在哈希表中查找是否含有0-(c+d)。

        2.在 Python 中,字典是一种键-值对(key-value pair)的数据结构,而 dict() 是用来创建一个空字典的构造函数。

        3.在 Python 字典(hashmap)中统计键值对应的出现次数的常见写法:hashmap.get(n1+n2, 0) 是获取字典中键为 n1 + n2 的值,如果该键不存在则返回默认值 0。hashmap[n1 + n2] = hashmap.get(n1 + n2, 0) + 1 将字典中键为 n1 + n2 的值加 1,相当于统计了 n1 + n2 出现的次数。

提交代码:

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        hashmap = dict()
        for a in nums1:
            for b in nums2:
                hashmap[a+b] = hashmap.get(a+b,0)+1
        count = 0
        for c in nums3:
            for d in nums4:
                key = 0-c-d
                if key in hashmap:
                    count += hashmap[key]
        return count


383. 赎金信 

题目链接:力扣题目链接

提交代码:

class Solution: #自己尝试按字母异位词的思路写了一版
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        count = [0]*26
        for i in ransomNote:
            count[ord(i)-ord('a')] += 1
        for j in magazine:
            count[ord(j)-ord('a')] -= 1
        for k in range(26):
            if count[k] > 0:
                return False
        return True

15. 三数之和

题目链接:力扣题目链接

笔记:

        哈希表中去重比较麻烦,所以本题不用哈希法。本题比较好理解的一个方法是双指针法,重点在于对结果进行去重。首先对整个数组进行一个排序,nums.sort() 是一个用于对列表 nums 进行排序(按升序)的方法。

提交代码:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        result = []
        nums.sort()
        
        for i in range(len(nums)):
            # 如果第一个元素已经大于0,不需要进一步检查
            if nums[i] > 0:
                return result
            
            # 跳过相同的元素以避免重复
            if i > 0 and nums[i] == nums[i - 1]:
                continue
                
            left = i + 1
            right = len(nums) - 1
            
            while right > left:
                sum_ = nums[i] + nums[left] + nums[right]
                
                if sum_ < 0:
                    left += 1
                elif sum_ > 0:
                    right -= 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
                        
                    right -= 1
                    left += 1
                    
        return result

过程中报错:

        1.if语句中return是直接跳出循环得到最终结果了,continue则是跳出本轮循环,接着下一轮循环。

        2.注意别漏下right>left 的约束!!


18. 四数之和

题目链接:力扣题目链接

笔记:

        1.思路上延续三数之和的做法,在外层再嵌套一个for循环即可。重点在于循环的剪枝和去重方面有一些区别。比如说排序后第一个元素>target并不意味着要直接剪掉,因为会出现负数,所以会出现越加越小的情况。

        2.由于有两层for循环,所以有两级的剪枝和去重操作。

提交代码:

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

过程中报错:

        注意left+1和right-1写在循环的哪里(只有分类讨论sum==target的时候才对二者同时进行操作)

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值