LC 454, 15, 18 Hash table 2

# LC 454, 15, 18 Hash table 2

---

  Second part of hash table.


 

## LC 454. 4Sum II

[第454题.四数相加II](https://programmercarl.com/0454.%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0II.html#)

___

### 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.

```python

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题. 三数之和](https://programmercarl.com/0015.%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C.html)

### Naive solution - brute force

#### Logic

+ Literally check every triplets in three `for` loop, which result in a time complexity of $O(n^3)$.

+ 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**.

```python

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

+ The source code could be found here: [第15题. 三数之和](https://programmercarl.com/0015.%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C.html).

### 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.

```python

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题. 四数之和](https://programmercarl.com/0018.%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C.html)

### 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".

```python

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)$ to $O(n^3)$.

```python

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值