代码随想录打卡(7) —— 哈希表

力扣454. 四数相加 II

仍然使用了defaultdict方法简化判断键值是否存在对步骤。小技巧是分组计算然后寻找对应值,将时间复杂度由暴力法的n^4降低到n^2。

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        import collections
        # 除了暴力解法,可以先计算1+2数组之和存入dic,在从3+4数组中找到对应-(1+2)的值
        dic_12 = defaultdict(int)  # 不用defaultdict可以先行判断键是否存在,如不存在需先插入键值对
        count = 0
        for i in nums1:
            for j in nums2:
                dic_12[i + j] += 1
        
        for m in nums3:
            for n in nums4:
                if -(m + n) in dic_12:
                    count += dic_12[-(m + n)]
        
        return count

力扣383.赎金信

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        dic_mag = collections.defaultdict(int)
        for i in magazine:
            dic_mag[i] += 1

        for j in ransomNote:
            if j in dic_mag and dic_mag[j] != 0:
                dic_mag[j] -= 1
            else:
                return False

        return True

力扣15.三数之和

用双指针,思路稍微有点小trick,细节比较多,去重比较复杂,稍微有点难度,不过还算好理解。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 排序方便去重和剪枝
        nums.sort()
        s = len(nums)
        result = []
        for i in range(s): # i作为第一个数,left第二个数,right第三个数
            left = i + 1 
            right = s - 1
            if nums[i] > 0:   # 剪枝
                break
            if i >= 1 and nums[i] == nums[i - 1]: #对i进行去重,上一次循环机判断的相同i与left + right的组合,注意是i-1不能是i+1(left对应的数)
                continue
            while left < right: # 对于每个固定位置i的left和right的组合循环
                sum_ = nums[i] + nums[left] + nums[right]
                if sum_ == 0:
                    result.append([nums[i],nums[right],nums[left]])
# 进行下一次移动前对left和right去重,由于单轮循环内,如和为0,i固定,left和left+1相同,那么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 
                if sum_ < 0: #组合过小,由于数组已排序,left右移和变大
                    left += 1
                if sum_ > 0:
                    right -= 1
        return result

力扣18.四数之和

比三数之和复杂,注意cur和pre两个都不确定,移动left和right,所以可能会出现排序后,pre最前面的指针对应的数(最小)大于target,但是和cur相加后又可以小于等于target(负数情况)。

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        # 与三数之和类似,注意存在两个变量数,如为附属,相加可能存在更小,注意left和right指针的移动条件
        nums.sort()
        s = len(nums)
        result = []
        for pre in range(s):
            # 对指针pre进行剪枝
            if nums[pre] > 0 and nums[pre] > target:
                continue
            # 对指针pre进行去重
            if pre > 0 and nums[pre] == nums[pre - 1]:
                continue
            for cur in range(pre + 1,s):
                # 对cur指针进行去重
                if cur > pre + 1 and nums[cur] == nums[cur - 1]:
                    continue
                left = cur + 1
                right = s - 1
                while left < right: # 当cur = n - 1时,left = n > right不进入循环
                    if nums[pre] + nums[cur] + nums[left] + nums[right] == target: 
                        result.append([nums[pre],nums[cur],nums[left],nums[right]])
                        while left < right and nums[left] == nums[left + 1]:
                            left += 1 # 防止越界需要加入left < right
                        while left < right and nums[right] == nums[right - 1]:
                            right -= 1
                        # 不用去重时
                        left += 1
                        right -= 1
                    elif nums[pre] + nums[cur] + nums[left] + nums[right] > target: # 大于目标值
                        right -= 1
                    elif nums[pre] + nums[cur] + nums[left] + nums[right] < target: # 小于目标值
                        left += 1
        return result


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值