LC 454, 15, 18 Hash table 2

文章讨论了如何利用哈希表和双指针方法解决编程题目中的四数相加II(LC454)、三数之和(LC15)问题。通过示例代码展示了哈希表在记录当前和并查找目标补数时的作用,以及双指针如何有效地减少时间复杂度从O(n^3)降低到O(n^2)。同时,提到了处理重复值和优化搜索过程的策略。
摘要由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、付费专栏及课程。

余额充值