LC 0018 [M] 4Sum - ALawliet/algorithms GitHub Wiki

prereq: 3sum


the difference from 3Sum is to include j we have to add another loop and addend

https://www.youtube.com/watch?v=EYeR-_1NRlQ&ab_channel=NeetCode

# O(n^3)
for # 1
  for # 2
    while l < r # 3, 4 (2Sum II)
class Solution:
    def fourSum(self, arr: List[int], target: int) -> List[List[int]]:
        n = len(arr)

        def threesum(i): # same as 3Sum
          start = i+1

          for j in range(start, n - (4-2)): # new 
              if j > start and arr[j] == arr[j-1]: continue # new, check past left bound which is i+1
                
              l = j + 1 # if we have i and j, then use the rightmost which is j, and +1
              r = n - 1

              while l < r:
                s = arr[i] + arr[j] + arr[l] + arr[r] # just add another variable

                if s == target: 
                  quads.append([arr[i], arr[j], arr[l], arr[r]]) # just add another variable
                  while l < r and arr[l] == arr[l+1]: l += 1 
                  while l < r and arr[r] == arr[r-1]: r -= 1
                  l += 1 ; r -= 1

                elif s < target: # total is too small, go bigger values
                  l += 1

                elif s > target: # total is too big, go smaller values
                  r -= 1 
        
        arr.sort()
        quads = []
        for i in range(0, n - (4-1)):
            if i > 0 and arr[i] == arr[i-1]: continue

            threesum(i) # same as 3Sum but add another outer loop variable

        return quads
class Solution:
    def fourSum(self, arr: List[int], target: int) -> List[List[int]]:
        n = len(arr)

        def search_pairs(i, j): # same as 3Sum
          l = j + 1 # if we have i and j, then use the rightmost which is j, and +1
          r = n - 1

          while l < r:
            s = arr[i] + arr[j] + arr[l] + arr[r]

            if s == target: 
              quads.append([arr[i], arr[j], arr[l], arr[r]])
              while l < r and arr[l] == arr[l + 1]: l += 1 
              while l < r and arr[r] == arr[r - 1]: r -= 1
              l += 1 ; r -= 1

            elif s < target:
              l += 1

            elif s > target:
              r -= 1 
        
        arr.sort()
        quads = []
        for i in range(0, n - (4-1)): # 4sum, new
            if i > 0 and arr[i] == arr[i-1]: continue

            for j in range(i+1, n - (3-1)): # 3sum 
              if j > i+1 and arr[j] == arr[j - 1]: continue # new, check past left bound which is i+1

              search_pairs(i, j) # same as 3Sum but add j

        return quads
class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        res = []
        
        def kSum(k, start, target, quad):
            if k != 2:
                for i in range(start, len(nums) - k + 1): # if k == 4, then leave the last 3
                    if i > start and nums [i] == nums[i-1]:
                        continue
                    kSum(k - 1, i + 1, target - nums[i], quad + [nums[i]])
            else:
                # at this point, target remains after the first 2 numbers subtracted, so find the last 2 numbers (l, r)
                # base case, two sum II
                l, r = start, len(nums) - 1
                while l < r:
                    if nums[l] + nums[r] < target:
                        l += 1
                    elif nums[l] + nums[r] > target:
                        r -= 1
                    else:
                        res.append(quad + [nums[l], nums[r]])
                        # l += 1
                        # while l < r and nums[l] == nums[l-1]: l += 1
                        while l < r and nums[l] == nums[l+1]: l += 1 
                        while l < r and nums[r] == nums[r-1]: r -= 1
                        l += 1 ; r -= 1

        kSum(4, 0, target, [])
        return res