4Sum
- Difficulty: Medium
- Primary pattern: Arrays & Strings
- Tags: Array, Two Pointers, Sorting
- Time taken: 10:14
- LeetCode Link
Key Idea
- Lock i and j, then move Left and Right
- Left and Right are dynamic, dont try and manage 4 pointers at ones, always lock to only 2 dynamic
Solution
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
# Inputs: List[int], int
# Outputs: List[List[int]]
# Description:
# all unique quadruplets that nums[a] + nums[b] + nums[c] + nums[d] == target
# 0 <= a, b, c, d < n
# a, b, c, and d are distinct.
# Sort according to size
nums.sort()
# Initialize
output_list = []
n = len(nums)
# Iterate
# Fix i
for i in range(n-3):
# Skip duplicate
if i > 0 and nums[i] == nums[i-1]:
continue
# Fix j
for j in range(i + 1, n -2):
# Skip duplicate
if j > i + 1 and nums[j] == nums[j - 1]:
continue
# [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
# ^ ^ ^ ^
# i j L R
left = j + 1
right = n - 1
while left < right:
current_sum = nums[i] + nums[j] + nums[left] + nums[right]
if current_sum == target:
output_list.append([nums[i], nums[j], nums[left], nums[right]])
left += 1
right -= 1
# Move if it is duplicate digit
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
elif current_sum < target:
left += 1
else:
right -= 1
return output_list
Complexity
- Time: O(n^3) ``` first loop i -> O(n) second loop j -> O(n) two-pointer scan -> O(n)
Total: O(n × n × n) = O(n^3) Why not O(n^4)? Because after fixing i and j, left and right do one linear scan, not a nested loop. ```
- Space: O(1)