python brush title--sum of N numbers problem (double pointer + pruning)

Posted by taskagent on Thu, 03 Feb 2022 18:57:56 +0100

1. Sum of two numbers (double pointer)

This was done earlier, using a hash table, with a time complexity of N

But if you change your mind and use the double pointer you learned today, it will be easy to understand, although it will not decrease or increase in time complexity (the sorting complexity is NlogN).

Idea: Sort first to get an ordered list, one pointer to the beginning and one to the end of the list. For each state, move the right pointer to the left if it is larger than the target value, and move the left pointer to the right if it is smaller than the target value. This method is suitable for finding solutions without duplication.

Personal questions:

# note 1
class Solution:
    def twoSum(self, nums: List[int], target: int):
        res = []
        i, j = 0, len(nums)-1
        nums.sort()
        for i in range(len(nums)):
            if i > 0 and nums[i-1] == nums[i]:
                continue
            while i < j and nums[i] + nums[j] > target:
                j -= 1
            if i == j:  # Notes 2,3
                break
            if nums[i] + nums[j] == target:
                res.append([nums[i], nums[j]])
        return res

Note 1:#Note that this is not a title: A solution to the sum of two numbers, which is coded only if the sum of the following three and four numbers is the same (only the target value must be returned, not the index)

Note 2:#There are only two cases where i=j can result. One: from the inner loop, the previous state nums[i]+nums[j] of the current state is larger than the target, at this time the sum of the two numbers is expected to be reduced, but the pointer J controlling the decrease can no longer move to the left, so the loop ends two: from the outer loop, then the previous state nums[i]+nums[j] of the current state is smaller than the target, at this time the sum of the two numbers is expected to be increased. But pointer i, which controls the increase, can no longer move to the right, and the loop ends

Note 3: When this happens (the sum of the two numbers expected to increase, but pointer i controlling the increase cannot be moved to the right). So can't j move right (back)?

A: No. It looks like j moves to the right, and I in this state is a new set of i,j combinations that have not been traversed, so why not?

Let's assume this is true. Assuming that the positions of I and j are I0 and j0 respectively before moving, j0 moves to the right and then moves to a J1 position, where nums[i0]+nums[j1] has a value greater than or equal to 0 (or the target value), and if I is I1 at the beginning, then when J first moves to J1 position, I is at I1 position, nums[i1]+nums[j1] at this time is less than nums[i0]+nums[j1], and nums[j1] J1 moves to j0 to make the whole value smaller, so the first nums [i1]+nums [j1] must be greater than 0, so comparing the two states, I1 and J1 are greater than 0, then I1 will no longer increase to i0, so it is not consistent with the idea that the value we set at the beginning decreases when it is larger and the value increases when it is smaller.

2.Sum of Three Numbers

Title: https://leetcode-cn.com/problems/3sum/

Official Title:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        nums.sort()
        ans = list()
        
        # Enumeration a
        for first in range(n):
            # Requires a different number from the last enumeration
            if first > 0 and nums[first] == nums[first - 1]:
                continue
            # The pointer corresponding to c initially points to the rightmost end of the array
            third = n - 1
            target = -nums[first]
            # Enumeration b
            for second in range(first + 1, n):
                # Requires a different number from the last enumeration
                if second > first + 1 and nums[second] == nums[second - 1]:
                    continue
                # You need to make sure that the pointer for b is on the left side of the pointer for c
                while second < third and nums[second] + nums[third] > target:
                    third -= 1
                # If pointers coincide, increase with b
                # There will be no C that satisfies a+b+c=0 and b<c, so you can exit the loop
                if second == third:
                    break
                if nums[second] + nums[third] == target:
                    ans.append([nums[first], nums[second], nums[third]])
        
        return ans

Author: LeetCode-Solution
 Links: https://leetcode-cn.com/problems/3sum/solution/san-shu-zhi-he-by-leetcode-solution/
Source: Force buckle ( LeetCode)
Copyright belongs to the author. For commercial reprinting, please contact the author for authorization. For non-commercial reprinting, please indicate the source.

The same idea is to put another cycle on the outside.

3. Sum of Four

Title: https://leetcode-cn.com/problems/4sum/

The whole idea is the same, you can see that there are more pruning operations (filter out unnecessary loops by judgment)

Official Title:

https://leetcode-cn.com/problems/4sum/solution/si-shu-zhi-he-by-leetcode-solution/https://leetcode-cn.com/problems/4sum/solution/si-shu-zhi-he-by-leetcode-solution/

Topics: Python Algorithm