LeetCode Problem: Two Sum II — Input Array Is Sorted
Difficulty: Medium
Topics: Array, Two Pointers, Binary Search
Series: LeetCode Interview Preparation — From Beginner to Expert
In our first LeetCode article, we solved Two Sum using a Hash Map.
Now we're going to revisit the same fundamental problem—but with one important change:
The array is already sorted.
That single constraint completely changes our strategy.
Instead of using extra memory with a Hash Map, we can use one of the most important interview patterns in DSA:
This pattern appears everywhere in technical interviews, especially in problems involving:
If you're preparing for coding interviews, Two Pointers is a pattern you absolutely need to master.
You are given a 1-indexed array of integers:
numbersthat is already sorted in non-decreasing order.
You are also given:
targetFind two numbers such that:
numbers[i] + numbers[j] = targetwhere:
1 <= i < j <= numbers.lengthReturn their indices.
You may assume that exactly one solution exists.
Consider:
numbers = [2, 7, 11, 15]
target = 9We need:
2 + 7 = 9Therefore:
Output:
[1, 2]Remember that LeetCode's problem uses 1-based indexing here.
So:
2 → index 1
7 → index 2In the original Two Sum problem, the array wasn't necessarily sorted.
We used a Hash Map:
number → indexBut now the input is sorted:
[2, 7, 11, 15]That gives us valuable information.
If our current sum is:
2 + 15 = 17and the target is:
9our sum is too large.
Because the array is sorted, we know that moving the right pointer to the left will make the number smaller.
Therefore:
Move right pointer left.Similarly, if:
2 + 7 = 9we're done.
And if:
2 + 7 = 9were too small, we'd move the left pointer right to increase the sum.
This is the magic of sorted data.
Place two pointers:
left
rightat opposite ends.
For:
[2, 7, 11, 15]we start:
L R
↓ ↓
[2, 7, 11, 15]Calculate:
2 + 15 = 17Target:
9Since:
17 > 9we need a smaller sum.
Move:
right--Now:
L R
↓ ↓
[2, 7, 11, 15]Calculate:
2 + 11 = 13Still too large.
Move right again:
L R
↓ ↓
[2, 7, 11, 15]Now:
2 + 7 = 9Found it.
The algorithm is extremely simple.
Set:
left = 0
right = len(numbers) - 1Calculate:
current_sum = numbers[left] + numbers[right]Compare the sum with the target.
If:
current_sum == targetreturn the indices.
If:
current_sum < targetmove:
left += 1If:
current_sum > targetmove:
right -= 1Continue until the pointers meet.
def twoSum(numbers, target):
left = 0
right = len(numbers) - 1
while left < right:
current_sum = numbers[left] + numbers[right]
if current_sum == target:
return [left + 1, right + 1]
elif current_sum < target:
left += 1
else:
right -= 1
return []Notice:
left + 1
right + 1because the problem uses 1-based indexing.
This is the most important part of the problem.
Suppose:
numbers = [1, 3, 5, 7, 9]
target = 10Initially:
1 + 9 = 10Done.
But suppose target were:
12We start with:
1 + 9 = 10The sum is too small.
Could moving right help?
No.
Moving right left would make the right value smaller:
1 + 7 = 8That's even worse.
So the only useful move is:
left++Now:
3 + 9 = 12Found.
Memorize these rules—not the code.
current_sum < targetWe need a larger sum.
Therefore:
left++current_sum > targetWe need a smaller sum.
Therefore:
right--current_sum == targetWe've found the answer.
Let's use a slightly larger example:
numbers = [2, 3, 4, 8, 11, 15]
target = 12Initially:
left = 0
right = 5Values:
2 + 15 = 17Too large.
Move right:
right = 4Now:
2 + 11 = 13Still too large.
Move right:
right = 3Now:
2 + 8 = 10Too small.
Move left:
left = 1Now:
3 + 8 = 11Still too small.
Move left:
left = 2Now:
4 + 8 = 12Found.
Answer:
[3, 4]because the problem uses 1-based indexing.
| Left | Right | Left Value | Right Value | Sum | Action |
|---|---|---|---|---|---|
| 0 | 5 | 2 | 15 | 17 | Move right |
| 0 | 4 | 2 | 11 | 13 | Move right |
| 0 | 3 | 2 | 8 | 10 | Move left |
| 1 | 3 | 3 | 8 | 11 | Move left |
| 2 | 3 | 4 | 8 | 12 | Found |
Final answer:
[3, 4]At first glance, you might think we're repeatedly searching the array.
We're not.
Each pointer only moves in one direction.
The left pointer starts at:
0and can move at most:
n - 1steps.
The right pointer also moves at most:
n - 1steps.
Together, they perform at most roughly n useful pointer movements.
Therefore:
Time Complexity = O(n)We only use:
left
right
current_sumNo additional array or hash map is required.
Therefore:
Space Complexity = O(1)This is one of the biggest advantages over the Hash Map solution.
Now we can compare our first Two Sum problem with this one.
| Approach | Array Requirement | Time | Extra Space |
|---|---|---|---|
| Hash Map | Unsorted okay | O(n) average | O(n) |
| Two Pointers | Must be sorted | O(n) | O(1) |
This teaches an extremely important interview lesson:
Input constraints are often clues to the intended algorithm.
If the interviewer tells you:
"The array is sorted."
Don't ignore that information.
Ask:
"Can I exploit the sorted order?"
Very often, the answer is yes.
We could.
For example:
def twoSum(numbers, target):
seen = {}
for i, num in enumerate(numbers):
complement = target - num
if complement in seen:
return [seen[complement] + 1, i + 1]
seen[num] = i
return []This would work.
But we're using:
O(n)extra memory even though the sorted property allows us to solve the problem using:
O(1)space.
A strong interview candidate doesn't just find a solution.
They look for the best solution under the given constraints.
Suppose:
current_sum < targetYou need a bigger sum.
Moving:
right--would make the right value smaller.
That's the wrong direction.
Correct:
left++This problem is slightly different from normal Python indexing.
Python uses:
0, 1, 2, 3...But the problem expects:
1, 2, 3, 4...Therefore:
return [left + 1, right + 1]is necessary.
This technique depends on the array being sorted.
Consider:
[8, 1, 7, 3, 5]You cannot blindly use the same pointer logic.
Why?
Because moving a pointer no longer guarantees that the sum will increase or decrease predictably.
The sorted property is what makes the algorithm work.
You might think:
numbers.sort()and then use two pointers.
But if the problem asks for original indices, sorting destroys the relationship between values and their original positions.
If sorting is allowed, you'd need to preserve the original indices.
But for Two Sum II, the array is already sorted, so we don't have this problem.
Two Sum II gives us a reusable pattern:
Sorted Array
↓
L R
↓ ↓
[ ... ... ... ... ]
↓
Calculate Sum
↓
┌───────┼───────┐
↓ ↓ ↓
Too Low Equal Too High
↓ ↓ ↓
L++ Found R--This pattern is incredibly powerful.
Once you understand this problem, you'll start seeing two pointers everywhere.
Check characters from both ends:
L → ← RMove inward.
Use one pointer to read and another to write.
Use two pointers at the ends and move the limiting side.
Sort the array and combine:
one fixed pointer
+
two-pointer searchUse separate pointers to traverse both arrays.
Use:
slow
fastpointers.
This becomes the famous Fast & Slow Pointer pattern.
During an interview, look for these signals:
Whenever you see a sorted array + pair relationship, immediately consider:
Two Pointers.
Don't start by saying:
"I remember Two Sum II uses two pointers."
Instead, reason your way to it.
You can tell the interviewer:
"Because the array is sorted, I can place one pointer at the beginning and one at the end. If their sum is smaller than the target, I need a larger value, so I move the left pointer forward. If their sum is larger, I move the right pointer backward. Each pointer moves at most n times, giving O(n) time and O(1) extra space."
That's a much stronger answer.
You're demonstrating understanding rather than memorization.
Why are two pointers so efficient?
Because the pointers never move backward.
For example:
left:
0 → 1 → 2 → 3 → ...
right:
n-1 → n-2 → n-3 → ...Every movement eliminates a set of impossible pairs.
That's the deeper reason the algorithm is linear.
We're not checking:
every pairWe're systematically eliminating possibilities.
Yes.
For each number:
complement = target - numberwe could binary-search for the complement.
That would produce approximately:
O(n log n)time.
But Two Pointers is better here:
O(n)and uses:
O(1)extra space.
This is another useful interview lesson:
Knowing multiple approaches helps you choose the best one.
Once you solve Two Sum II, the interviewer may increase the difficulty.
What if there are multiple valid pairs?
Now you might need to find all valid pairs.
What if the array is not sorted?
You can discuss:
and explain the trade-offs.
What if we need three numbers?
This leads directly toward:
3Sum — LeetCode #15
The standard solution uses:
Sorting
+
Two PointersWhat if we need four numbers?
This leads toward:
4Sum — LeetCode #18
and more advanced variations.
What if we need the pair whose sum is closest to the target?
Now you modify the pointer logic to track:
minimum absolute differenceOur series is now developing recognizable patterns.
Pattern:
Hash MapPattern:
Running MinimumPattern:
Hash SetPattern:
Kadane's AlgorithmPattern:
Two PointersThis is how you should study LeetCode.
Don't think:
"I need to solve 500 random problems."Think:
"I need to master the major problem-solving patterns."Once you understand a pattern, many problems become variations of the same idea.
Problem:
Find two numbers in a sorted array
whose sum equals target.
Input:
Sorted array.
Technique:
Two Pointers.
Initialize:
left = 0
right = n - 1
While left < right:
current_sum =
numbers[left] + numbers[right]
If current_sum == target:
return indices
If current_sum < target:
left += 1
Else:
right -= 1
Complexity:
Time: O(n)
Space: O(1)Before moving to the next article, try these:
Find whether a sorted array contains a pair with a given sum.
Find all unique pairs with a target sum.
Find the pair whose sum is closest to the target.
Solve 3Sum using sorting and two pointers.
Solve 4Sum.
Determine whether a string is a palindrome using two pointers.
These problems will turn the Two Pointer technique into a natural instinct.
The biggest lesson from LeetCode #167 isn't the code.
It's this:
Sorted data contains information. Use it.
In the original Two Sum problem, we needed a Hash Map because the array gave us no ordering information.
In Two Sum II, the array is sorted.
That allows us to replace:
Hash Map
O(n) spacewith:
Two Pointers
O(1) spaceThe algorithm is simple:
Sum too small → move left
Sum too large → move right
Sum equal → answerBut the deeper interview skill is recognizing why those pointer movements are valid.
That's the difference between memorizing a LeetCode solution and actually understanding algorithms.
As this Kairos Coders series progresses, we'll keep building these patterns one by one—until problems that initially look completely unfamiliar start looking like combinations of techniques you've already mastered.
Pixels to Perfection Design that Impresses