LC 454, 15, 18 Hash table 2

文章介绍了使用哈希表和双指针解决LeetCode中的454题四数相加II和15题三数之和的问题。对于三数之和,提到了暴力求解和优化过的双指针方法。在四数相加问题中,讨论了如何利用哈希表存储中间结果并减少重复计算,以提高效率。
摘要由CSDN通过智能技术生成

LC 454, 15, 18 Hash table 2


Second part of hash table.

LC 454. 4Sum II

第454题.四数相加II


Logic

The logic is about the same as the “3 sum”, “2 sum” problems. What need to be done is just record the current sum in a dict, and upon the time the complement to the target, 0, is found in the dict, we can imncrease the accumulator.

def fourSumCount(
    self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]
) -> int:
    dict1 = defaultdict(int)
    count = 0
    for i in nums1:
        for j in nums2:
            dict1[i + j] += 1
    for i in nums3:
        for j in nums4:
            key = 0 - i - j
            count += dict1[key]
    return count

LC 15. 3Sum


第15题. 三数之和

Naive solution - brute force

Logic
  • Literally check every triplets in three for loop, which result in a time complexity of O ( n 3 ) O(n^3) O(n3).
  • We can fix the first number for the second for loop and fix the first pair of sum for the third for loop, which helps a little.
  • There are more things to add, for example, one could skip some pairs which are seen before. I only added the tup set for removing duplicate.
def threeSum(self, nums: List[int]) -> List[List[int]]:
    # naive
    nums.sort()
    ret = []
    tup = set()
    for i in range(len(nums)-2):
        diff = 0 - nums[i]
        for j in range(i+1, len(nums)-1):
            diff2 = diff - nums[j]
            for k in range(j+1, len(nums)):
                if diff2 == nums[k]:
                    temp = tuple((nums[i], nums[j], nums[k]))
                    if temp not in tup:
                        ret.append([nums[i], nums[j],nums[k]])
                        tup.add(temp)
    return ret

Dict

Duo Ptrs

Logic

To use duo-pointers to solve this problem, one could think of each pairs as a prefix sum, then linearly search for the complement of the target.

def threeSum2(self, nums: List[int]) -> List[List[int]]:
    nums.sort()
    ret = set()
    for i in range(len(nums)):
        if i > 0 and nums[i] == nums[i - 1]:
            continue
        j = i + 1
        k = len(nums) - 1
        while j < k:
            s = nums[j] + nums[k]
            if s + nums[i] < 0:
                j += 1
            elif s + nums[i] > 0:
                k -= 1
            else:
                ret.add((nums[i], nums[j], nums[k]))
                j += 1
                k -= 1
                while j < k and nums[j] == nums[j - 1]:
                    j += 1
                while j < k and nums[k] == nums[k + 1]:
                    k -= 1
    return [list(i) for i in ret]

LC 18 4Sum


第18题. 四数之和

Dict method

Logic
  • Using the dict, we could save the sum so far for each pair of nums, then check for other pairs if their complement are already in the dict.
  • To reduce some of the duplicates, we limit the maximum occurance of an item to a maximum of 4, because we are doing a “4Sum”, and seeing 5 same “2” won’t change the result as 4 “2”.
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
    dict1 = defaultdict(list)
    visited = set()
    ct = Counter(nums)
    for key in ct:
        ct[key] = min(4, ct[key])
    nums = sorted(ct.elements())
    for i in range(len(nums) - 1):
        for j in range(i + 1, len(nums)):
            key = nums[i] + nums[j]
            dict1[key].append([i, j])
            if target - key in dict1:
                for pair in dict1[target - key]:
                    x, y = pair
                    keyLst = [nums[i], nums[j], nums[x], nums[y]]
                    keyLst = tuple(keyLst)
                    if i not in pair and j not in pair and keyLst not in visited:
                        visited.add(keyLst)
    return list(visited)

Duo ptrs

Logic
  • Like other sum problems, we could fix the sum of the first two numbers, then using two pointers to find the last two numbers which reduce the brute force runtime from O ( n 4 ) O(n^4) O(n4) to O ( n 3 ) O(n^3) O(n3).
def fourSum2(self, nums: List[int], target: int) -> List[List[int]]:
    nums.sort()
    ret = []
    for i in range(len(nums) - 1):
        if nums[i] > target and nums[i] >= 0:
            break
        if i > 0 and nums[i - 1] == nums[i]:
            continue
        for j in range(i + 1, len(nums)):
            fixed_sum = nums[i] + nums[j]
            if fixed_sum > target and fixed_sum >= 0:
                break
            if j > i + 1 and nums[j] == nums[j - 1]:
                continue
            left = j + 1
            right = len(nums) - 1
            while left < right:
                if fixed_sum + nums[left] + nums[right] > target:
                    right -= 1
                elif fixed_sum + nums[left] + nums[right] < target:
                    left += 1
                else:
                    ret.append([nums[i], nums[j], nums[left], nums[right]])
                    right -= 1
                    left += 1
    return ret

Summary:


  • When dealing with the “3Sum”, “4Sum” problems, we may consider using duo-pointers rather than the hash table to reduce a bit of the runtime.

  • Meanwhile, we need to figure out when it is best to reduce the duplicates and skip some condition that we have already faced.

  • Total time: About 3 hrs.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值