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

文章讲述了如何通过哈希表和双指针技巧优化四数和问题(如454.四数相加II和18.四数之和)的解法,降低时间复杂度,从O(n^4)提升到O(n^2),并展示了Python代码实现。
摘要由CSDN通过智能技术生成

今天继续练习哈希表, 有部分leetcode练习题用了双指针。 

454.四数相加II

思路:四个列表中每个列表出一个数字,四个相加等于0。 BruteForce 可以循环四个列表, 找到所有的组合判断是否相加为0。 时间复杂度 O(n^4) 空间复杂度 O(1)。 由于output只需要输出组合的个数, 组合的数字或者下标不需要care。 所以考虑用字典记录前两个列表数字组合相加的合出现的次数。 然后循环后两个列表, 找到哈希表对应 -num3-num4 的key对应的值即可,然后将所有这种值相加即可。时间复杂度O(n^2).

难点: 空间换时间

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        # 1. 使用 hash map 记录所有 nums1 和 nums2 元素相加的组合
        record2 = defaultdict(int) # key: num1+num2, value: number of sum12 occurrences
        for i in range(len(nums1)):
            for j in range(len(nums2)):
                record2[nums1[i]+nums2[j]] += 1
        # 2. loop all elements in nums3 and nums4 and calculate sum34 = num3+num4
        # find -sum34 in hash table
        rlst = 0
        for i in range(len(nums3)):
            for j in range(len(nums4)):
                sum34 = nums3[i] + nums4[j]
                target = -sum34
                rlst += record2[target]
        return rlst

383. 赎金信  

思路: 用字典记录字符串2 每个字母出现的次数, 循环字符串1,对应每个字符, 字典的key 对应的value -1。 如果字典的value 有小于0 的数字,  返回错误,反之返回True。 这道题我学习了一下 python 中 collections.Counter 的用法。 

难点: 无

from collections import Counter
class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        c = Counter(magazine)
        c.subtract(ransomNote)
        return True if min(c.values()) >= 0 else False  

15. 三数之和

思路:找出一个列表中三数之和为0 的组合, bruteforce 可以循环三次做。时间复杂度 O(n^3)。 另外因为不需要输出数组的下标, 因此可以想到通过先排序在寻找, 降低时间复杂度。 排序之和, 是用双指针法,左右指针根据当前相加是否大于0, 往中间靠就可以了。

难点: 由于如果有重复的 triple 组合只需要给一个, 因此所有符合条件的triple组合写在set 中更方便。 另外, 可以加一些额外的判断条件,减少额外的循环, 但是本质上没有降低时间复杂度。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # sort the input array first
        nums = sorted(nums)
        # loop all element in nums, using two pointers method. 
        ans = set()
        for i, num in enumerate(nums):
            j = i+1
            k = len(nums) - 1
            while j < k:
                if num + nums[j] + nums[k] == 0:
                    ans.add((num, nums[j], nums[k]))
                    j += 1
                elif num + nums[j] + nums[k] < 0:
                    j += 1
                else:
                    k -= 1
        return ans

18. 四数之和 

思路: 同上一题

难点: 同上一题 

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums = sorted(nums)
        l = len(nums)
        ans = set()
        for i in range(l-3):
            for j in range(i+1, l-2):
                left = j+1
                right = l-1
                while left < right:
                    num4sum = nums[i] + nums[j] + nums[left] + nums[right]
                    if num4sum == target:
                        ans.add((nums[i], nums[j], nums[left], nums[right]))
                        left += 1
                        right -= 1
                    elif num4sum < target:
                        left += 1
                    else:
                        right -= 1
        return ans

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值