Medium difficulty 997

Give you a chance n An array of integers nums ， And a target value target . Please find and return the quads that meet all the following conditions and are not repeated [nums[a], nums[b], nums[c], nums[d]] (if two Quad elements correspond to each other, two quads are considered to be repeated):

- 0 <= a, b, c, d < n
- a,b,c and d Different from each other
- nums[a] + nums[b] + nums[c] + nums[d] == target

You can press Arbitrary order Return the answer.

Example 1:

Input: num = [1,0, - 1,0, - 2,2], target = 0 Output: [[- 2, - 1,1,2], [- 2,0,0,2], [- 1,0,0,1]]

Example 2:

Input: num = [2,2,2,2,2], target = 8 Output: [[2,2,2,2]]

Tips:

- 1 <= nums.length <= 200
- -109 <= nums[i] <= 109
- -109 <= target <= 109

### My analytical thinking:

With the basis of the sum of two numbers, I first thought of using the double pointer method to solve this problem; The whole debugging process is really difficult. Finally, with my own efforts, I finally got AC (although the space-time complexity is not very excellent).

The following points shall be noted during commissioning:

- The premise of double pointer should be sorted first
- If the title requires the same elements in the same position, it will be regarded as a repeated quadruple. Therefore, when dealing with the first element and the second element, I use f1 and f2 to mark the number of repeated elements respectively. If it is the same element, I will end this cycle until it is not a repeated element. It should be noted here: f2 in order to prevent the mark of the last cycle on the outermost layer from causing an error impact on the next result, it should be set to 0 before each cycle, otherwise an error will occur.
- For the repeated processing of the third element (left) each time, pay attention to: move to the position of the penultimate repeated value, because there may be a case where the fourth element (right) is the repeated value. We should also judge whether it is used. If it is not used, but continues to be used by ourselves, that is, repeated quads.
- Similarly, the fourth element is processed.
- After finding the target value, instead of jumping out of the loop, continue to move the third element. Because there may be a case where the addition of the two values in the middle is equal to the addition of the two numbers in the outer layer, it cannot be omitted.

My code:

class Solution: def fourSum(self, nums: List[int], target: int) -> List[List[int]]: result_ls = [] len_nums = len(nums) #Sort the lines so that you can use the double pointer method nums.sort() #print(nums) f1 = 0 f2 = 0 for element1 in range(len_nums - 3): if f1 > 0: f1 -= 1 continue f2 = 0 for element2 in range(element1 + 1, len_nums - 2): left = element2 + 1 right = len_nums - 1 if f2 > 0: f2 -= 1 continue while(left < right): sum = nums[element1] + nums[element2] + nums[left] + nums[right] #print(element1, element2, left, right) if sum == target: #print('resut',element1, element2, left, right) t_ls = [] t_ls.append(nums[element1]) t_ls.append(nums[element2]) t_ls.append(nums[left]) t_ls.append(nums[right]) result_ls.append(t_ls) left += 1 while left < right and nums[left] == nums[left - 1]: #print('left', left) left += 1 # The special case is that a value left to right is not used, but continues to be used by itself, that is, duplicate values sum_new = nums[element1] + nums[element2] + nums[left] + nums[right] if left + 1 == right and nums[left] == nums[left + 1] and (sum == target or sum_new > target): break elif sum < target: left += 1 #print('-2',left,right) while left + 1 < right and nums[left] == nums[left - 1]: #print('left', left) left += 1 # The special case is that a value left to right is not used, but continues to be used by itself, that is, duplicate values sum_new = nums[element1] + nums[element2] + nums[left] + nums[right] if left + 1 == right and nums[left] == nums[left + 1] and (sum == target or sum_new > target): break else: right -= 1 #print('-1',left,right) while left < right - 1 and nums[right] == nums[right + 1]: #print(' ri -1') right -= 1 sum_new = nums[element1] + nums[element2] + nums[left] + nums[right] # Similarly, the special case is a value left for left, which is not used, but continues to be used by itself, that is, duplicate values if left == right - 1 and nums[right] == nums[right - 1] and (sum == target or sum_new < target): #print('le == ri -1') break while element2 < left and nums[element2] == nums[element2 + 1]: #print('ele2', element2) element2 += 1 f2 += 1 while element1 < len_nums - 3 and nums[element1] == nums[element1 + 1]: #print('ele1', element1) element1 += 1 f1 += 1 return result_ls

Operation results:

### Reference answer:

analysis:

Sum of four, sum 15. Sum of three It's a train of thought. They all use double finger acupuncture. The basic solution is in 15. Sum of three A for loop is set on the basis of.

However, there are some details to pay attention to. For example, do not judge num [k] > target It returns. The sum of three can be passed nums[i] > 0 It returns, because 0 is already a certain number, and the sum of four numbers is an arbitrary value. (you can feel it by writing the code yourself)

15. Sum of three The double pointer solution of is a layer for loop with num[i] as the determined value, and then there are left and right in the loop. The following table is used as the double pointer. Find num[i] + num [left] + num [right] = = 0.

The double pointer solution of the sum of four numbers is a two-layer for loop. Num [k] + num [i] is the determined value. There are still left and right in the loop. The following table is used as the double pointer. Find out the case where num [k] + num [i] + num [left] + num [right] = = target. The time complexity of the sum of three numbers is O(n^2), and the time complexity of the sum of four numbers is O(n^3).

Then the same reason, the sum of five numbers, the sum of six numbers and so on all use this solution.

about 15. Sum of three The double finger needle method is to reduce the original solution of violence O(n^3) to O(n^2), and the double pointer solution of the sum of four numbers is to reduce the original solution of violence O(n^4) to O(n^3).

We talked about the classic topic of hash table before: 454. Adding four numbers II , it is much simpler than this question, because this question requires to find four numbers in a set, and the sum is equal to target. At the same time, four tuples cannot be repeated.

and 454. Adding four numbers II It's four independent arrays. Just find A[i] + B[j] + C[k] + D[l] = 0. It doesn't need to consider the case that the sum of four repeated elements is equal to 0, so it's much simpler than this problem!

Let's review that several topics use the double pointer method.

The double pointer method optimizes the solution of time complexity O(n^2) to O(n). In other words, it is reduced by one order of magnitude. The title is as follows:

Operation linked list:

- 206. Reverse linked list
- 19. Delete the penultimate node of the linked list
- Interview question 02.07. Linked list intersection
- Question 142. Circular linked list II

The double pointer method has many applications in string problems, which will be introduced later.

Reference code:

class Solution: def fourSum(self, nums: List[int], target: int) -> List[List[int]]: nums.sort() n = len(nums) res = [] for i in range(n): if i > 0 and nums[i] == nums[i - 1]: continue for k in range(i+1, n): if k > i + 1 and nums[k] == nums[k-1]: continue p = k + 1 q = n - 1 while p < q: if nums[i] + nums[k] + nums[p] + nums[q] > target: q -= 1 elif nums[i] + nums[k] + nums[p] + nums[q] < target: p += 1 else: res.append([nums[i], nums[k], nums[p], nums[q]]) while p < q and nums[p] == nums[p + 1]: p += 1 while p < q and nums[q] == nums[q - 1]: q -= 1 p += 1 q -= 1 return res

Operation results: