Leetcode - 3Sum (ideas to solve problems, refer to other people's code optimization, and wrong solutions)

Topic description

Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Now given an array of n integers, look for three numbers that add up to 0. Find all the different groups, each group consists of three numbers, and the sum of the three numbers is 0

Note:

The solution set must not contain duplicate triplets.

The rightmost result must be the set of repeated combinations without

Example 1:

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]

Example 2:

Input: nums = []
Output: []

Example 3:

Input: nums = [0]
Output: []

Constraints: (limit)

0 <= nums.length <= 3000,The length of the array is less than 3000
-105 <= nums[i] <= 105,The element size of the array is±105 between

Thought analysis

  • Notice:

    • You cannot convert the list to a set, eliminate all the same elements, and the same elements can also add up to 0, such as 1, 1, -2
    • Make sure that the input list has three or more elements, otherwise there is no way to form a set
Brute-force cracking:
*Three kinds of loops, list all three-element combinations, and determine whether the addition is 0
* Determine if the last composition is in the set, if not, add it
  • Question: In python, if the elements of the list are the same, but the positions are different, is it the same list?
  • Answer: First of all, lists cannot be used as elements of sets. The data elements of sets must be hashable and immutable data types. Lists are mutable data types and cannot be used. If it is replaced by a tuple, the order is different, and it is still a different element. So it is not advisable to sort the elements before forming a tuple.

Code

python - law of violence
class Solution(object):
    def threeSum(self, nums):
        result = set()
        result2 = list()
        if len(nums)>=3:
              for i in range(len(nums)-2):
                  for j in range(i + 1,len(nums)- 1):
                      for k in range(j + 1,len(nums)):
                          if(nums[i] + nums[j] + nums[k] == 0):
                              result.add(tuple(sorted((nums[i],nums[j],nums[k]))))
              for i in range(len(result)):
                  result2.append(list(result.pop()))
              return result2
        else:
              return []

if __name__ == '__main__':
    test = Solution()
    nums = [-1,0,1,2,-1,-4]
    print(type(nums))
    print(test.threeSum(nums))
Test Results

  • Sure enough, the running time exceeded the limit, and I was stumbling when I wrote it myself. I just started using python, and I almost forgot what I learned before.
  • But to be honest, if I implement this method in C language, I don't have to write it, there are too many, it is difficult to just remove the same elements from the collection.
  • problems encountered
    • To create an object using a class in python, you need to add parentheses after the class name. If you don't add it, the following exception will occur. Object is not initialized.

    • The elements in the collection have requirements and must be immutable data structures, elements, strings, etc.; no mutable data structures, such as lists and dictionaries, can be used as elements.

    • Tuples with the same elements but in a different order are still different tuples

Improvement - how to reduce the time and number of traversals

  • Sort all the numbers into two arrays, positive and negative, with zero counted separately. In the end, zero can be formed, except for the extreme case of three zeros, there must be a positive number and a negative number.
  • Take a positive number and a negative number respectively, find all the combinations, and then search in the original array according to the sum of the two
  • At most 3000 elements, after all, there are a total of 15000*15000 combinations, which is not practical at all. Each combination also traverses the complete array once, which is not cost-effective.

Reference tutorial

Solution
  • For repeated numbers: sort the list, the same numbers must be together after sorting, so you can skip it directly
  • Combination of repetitions: fixed position, convert 3Sum into 2Sum, and avoid repetition in 2Sum, if the left and right boundary points are the same after moving, skip it

icon

Code
def threeSum(self,nums):
    result = list()
    if len(nums) >= 3:
        # Sort the original array to mask the effect of duplicate numbers
        nums.sort()
        # Divided into two traversals, the outermost traversal is to determine the first position where the three numbers are added, and the problem is simplified to 2Sum, and the second level of traversal is to determine the problem of solving 2Sum
        i = 0
        while i < len(nums):
            left = i + 1
            right = len(nums) - 1
            while left < right:
                if nums[left] + nums[right] == 0 - nums[i]:
                    result.append([nums[i], nums[left], nums[right]])

                    temp = 1
                    while left + temp < len(nums) and nums[left + temp] == nums[left]:
                        temp += 1
                    left = left + temp

                    temp = 1
                    while nums[right - temp] == nums[right]:
                        temp += 1
                    right = right - temp
                elif nums[left] + nums[right] > 0 - nums[i]:
                    temp = 1
                    while nums[right - temp] == nums[right]:
                        temp += 1
                    right = right - temp
                else:
                    temp = 1
                    while left + temp < len(nums) and nums[left + temp] == nums[left]:
                        temp += 1
                    left = left + temp
            temp = 1
            while i + temp < len(nums) and nums[i + temp] == nums[i]:
                temp += 1
            i += temp
        return result
    else:
        return []
operation result

Analysis and Summary
  • In actual operation, pay attention to the out-of-bounds problem of the array, whether it is the left boundary point or the right boundary point, it must be controlled
  • Going over all the same data methods, set the base step to 1, then increment by 1 item by item to get the final result.
Reference Code
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        res = []
        nums.sort()
        
        for i, a in enumerate(nums):
            if i > 0 and a == nums[i - 1]:
                continue
            # After the iteration, first determine whether the value is the same as the previous value. If it is the same, skip it directly and go to the next loop.
            
            l, r = i + 1, len(nums) - 1
            while l < r:
                threeSum = a + nums[l] + nums[r]
                if threeSum > 0:
                    r -= 1
                elif threeSum < 0:
                    l += 1
                # If the encounters are the same, there is no need to determine whether they are the same, the same will not play a role in reducing or increasing
                else:
                    res.append([a, nums[l], nums[r]])
                    l += 1
                    while nums[l] == nums[l - 1] and l < r:
                        l += 1
                    # There is no need to shrink both sides at the same time, just change one side and the other side will automatically balance
        return res
Analysis and Summary
  • enumerate(): Combine a traversable data object into an index sequence, and list data and data subscripts at the same time, generally used in for loops
    • enemerate (objects that can be traversed, where to start traversing)
>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
...     print i, element
... 
0 one
1 two
2 three

Tags: Python Algorithm leetcode

Posted by BlueSkyIS on Wed, 18 May 2022 09:50:36 +0300