Editorial
Core insight
3Sum Smaller · Two Pointers
Core Insight for 3Sum Smaller
The critical intuition for the optimal solution lies in how sorting transforms the problem. Once the array is sorted in ascending order, if we fix one element nums[i] and pick two other elements nums[left] and nums[right], we can predict the behavior of sums involving indices between left and right.
Consider the condition: nums[i] + nums[left] + nums[right] < target.
If this condition is true, we know that nums[right] is the largest available element in the current window . If the sum is strictly less than the target using the largest element (nums[right]), it must also be less than the target using any smaller element in the window (indices left+1 to right-1).
Visual Description:
Imagine the array indices plotted on a line. We anchor i at the start. We place left at i + 1 and right at the end of the array.
- We check the sum of the triplet.
- If the sum is less than target, it implies that the pair
(left, right)is valid. Crucially, because the array is sorted, the pairs(left, right-1),(left, right-2), ...(left, left+1)are also valid. They are all smaller than the current sum. - Instead of iterating
kfromleft+1torightto count them one by one, we can simply addright - leftto our total count. This batch counting is the optimization key. - After counting, we move
leftforward to see if we can find valid triplets with a larger second number.
If the sum is greater than or equal to target, the current right is too large. We must decrement right to reduce the total sum.
Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 259: 3Sum Smaller Solution & Explanation
Problem Overview
TL;DR: Sort the input array, iterate through the first element, and use the converging two-pointer technique to count all valid pairs for the remaining two elements in time.
The problem asks us to calculate the number of index triplets such that and the sum of the elements at these indices is strictly less than a given target value. Unlike the classic 3Sum problem which asks for unique triplets of values, LeetCode 259 requires us to count index triplets, meaning duplicate values in the array are treated as distinct elements. This is a popular interview question that tests your ability to optimize combinatorial search problems using sorting and pointers.
Brute Force Approach for 3Sum Smaller
The most straightforward method to solve the 3Sum Smaller problem is to iterate through every possible triplet of indices and check if their sum satisfies the condition.
We can use three nested loops to generate all combinations where .
1# Pseudo-code for Brute Force
2count = 0
3for i from 0 to n - 3:
4 for j from i + 1 to n - 2:
5 for k from j + 1 to n - 1:
6 if nums[i] + nums[j] + nums[k] < target:
7 count = count + 1
8return countComplexity Analysis: The time complexity of this approach is because of the three nested loops. If is 2000, is , which will result in a Time Limit Exceeded (TLE) error on most coding platforms. This approach fails because it performs redundant checks and does not utilize the properties of the data to prune the search space.
Algorithm Strategy: Two Pointer Patterns
- Sort: First, sort the array
numsin ascending order. This is a prerequisite for the two-pointer logic. - Iterate: Loop through the array with index
ifrom0ton-2. Thisirepresents the first element of the triplet. - Initialize Pointers: For each
i, initialize two pointers:left = i + 1right = n - 1
- Converge: While
left < right:- Calculate
current_sum = nums[i] + nums[left] + nums[right]. - Case 1 (
current_sum < target): We found a valid window. All elements fromleft + 1torightcan pair withleftto satisfy the condition.- Add
right - leftto the total count. - Increment
leftto explore larger values.
- Add
- Case 2 (
current_sum >= target): The sum is too large. We need a smaller sum.- Decrement
rightto reduce the sum.
- Decrement
- Calculate
- Return: After the outer loop finishes, return the total count.
Execution Flow
Let's trace nums = [-2, 0, 1, 3], target = 2.
- Sort:
[-2, 0, 1, 3](Already sorted). - Outer Loop
i = 0(nums[i] = -2):- Set
left = 1(nums[1] = 0),right = 3(nums[3] = 3). - Sum:
-2 + 0 + 3 = 1. - Check:
1 < 2is True. - Action: Since the sum is small enough, the pair
(0, 3)works. Additionally, any element betweenleftandrightcombined withleftwould be even smaller. - Count: Add
right - left=3 - 1=2. (Triplets are indices:(0,1,3)and(0,1,2)). - Move:
leftbecomes2. - New State:
left = 2,right = 3. - Sum:
-2 + 1 + 3 = 2. - Check:
2 < 2is False. - Action: Sum is too high (or equal).
- Move:
rightbecomes2. - Loop condition
left < right(2 < 2) is False. Break inner loop.
- Set
- Outer Loop
i = 1(nums[i] = 0):- Set
left = 2,right = 3. - Sum:
0 + 1 + 3 = 4. - Check:
4 < 2is False. - Move:
rightbecomes2. - Loop condition
2 < 2is False. Break.
- Set
- End: Return total count
2.
Proof of Correctness
The correctness relies on the sorted property of the array.
- Completeness: By fixing
iand scanning the remaining array withleftandright, we consider all valid positions for the second and third elements. - Counting Logic: When
nums[i] + nums[left] + nums[right] < target, the inequality holds for allkwhereleft < k <= rightbecausenums[k] <= nums[right]. Therefore,nums[i] + nums[left] + nums[k] <= nums[i] + nums[left] + nums[right] < target. Addingright - leftcorrectly counts exactly thesekvalues without individual checks. - Pointer Movement:
- If sum < target, increasing
leftallows us to test if a larger second number can still form a valid sum. - If sum >= target, decreasing
rightis the only way to reduce the sum, as decreasingleftis impossible (we move forward) and increasingleftwould only increase the sum.
- If sum < target, increasing
Pattern Reuse Notes
The Two Pointers - Converging pattern used in LeetCode 259 is fundamental for several array problems:
- LeetCode 11: Container With Most Water: Uses converging pointers to maximize area, moving the pointer pointing to the shorter line.
- LeetCode 15: 3Sum: Finds triplets summing to zero. Uses the same sorting + two-pointer logic but requires skipping duplicates.
- LeetCode 16: 3Sum Closest: Finds a triplet sum closest to a target. Uses the exact same traversal but tracks the minimum difference instead of counting.
- LeetCode 18: 4Sum: Extends the 3Sum logic by adding one more nested loop, reducing to .
Understanding the invariant in 3Sum Smaller—that satisfying the condition at the boundaries implies satisfaction for the whole range—is key to mastering this subpattern.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 259
1class Solution {
2public:
3 int threeSumSmaller(vector<int>& nums, int target) {
4 sort(nums.begin(), nums.end());
5 int count = 0;
6 int n = nums.size();
7
8 for (int i = 0; i < n - 2; ++i) {
9 int left = i + 1;
10 int right = n - 1;
11
12 while (left < right) {
13 // Check sum of current triplet
14 if (nums[i] + nums[left] + nums[right] < target) {
15 // If (i, left, right) is valid, then all pairs
16 // (i, left, left+1) ... (i, left, right) are valid.
17 count += (right - left);
18 left++;
19 } else {
20 // Sum is too large, decrease the largest element
21 right--;
22 }
23 }
24 }
25
26 return count;
27 }
28};Java Solution for LeetCode 259
1class Solution {
2 public int threeSumSmaller(int[] nums, int target) {
3 Arrays.sort(nums);
4 int count = 0;
5 int n = nums.length;
6
7 for (int i = 0; i < n - 2; i++) {
8 int left = i + 1;
9 int right = n - 1;
10
11 while (left < right) {
12 int sum = nums[i] + nums[left] + nums[right];
13
14 if (sum < target) {
15 // All indices between left and right satisfy the condition
16 // when paired with nums[i] and nums[left]
17 count += (right - left);
18 left++;
19 } else {
20 // Sum is too large, try smaller number
21 right--;
22 }
23 }
24 }
25
26 return count;
27 }
28}Python Solution for LeetCode 259
1class Solution:
2 def threeSumSmaller(self, nums: List[int], target: int) -> int:
3 nums.sort()
4 count = 0
5 n = len(nums)
6
7 for i in range(n - 2):
8 left = i + 1
9 right = n - 1
10
11 while left < right:
12 current_sum = nums[i] + nums[left] + nums[right]
13
14 if current_sum < target:
15 # If the sum is smaller than target, then nums[i] + nums[left]
16 # plus ANY element from index left+1 to right is also smaller.
17 count += (right - left)
18 left += 1
19 else:
20 # Sum is too large, move right pointer to reduce sum
21 right -= 1
22
23 return count