Given an array of integers numbers that is sorted in non-decreasing order.
Return the indices (1-indexed) of two numbers, [index1, index2], such that they add up to a given target number target and index1 < index2. Note that index1 and index2 cannot be equal, therefore you may not use the same element twice.
There will always be exactly one valid solution.
Your solution must use additional space.
Example 1:
Input: numbers = [1,2,3,4], target = 3
Output: [1,2]Explanation:
The sum of 1 and 2 is 3. Since we are assuming a 1-indexed array, index1 = 1, index2 = 2. We return [1, 2].
Constraints:
2 <= numbers.length <= 1000-1000 <= numbers[i] <= 1000-1000 <= target <= 1000
You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array.
A brute force solution would be to check every pair of numbers in the array. This would be an O(n^2) solution. Can you think of a better way?
Can you think of an algorithm by taking the advantage of array being sorted?
We can use the two-pointer algorithm. If nums[0] + nums[n-1] > target, then we know nums[n - 1] can not possibly be included in any pairs. Why? Because nums[n - 1] is the largest element in the array. Even by adding it with nums[0], which is the smallest element, we still exceed the target. You can think of the case when nums[0] + nums[n - 1] < target.
We keep two pointers, one at the start and the other at the end of the array. If the sum of the numbers at the two pointers is greater than the target, decrement the right pointer, else increment the left pointer. Repeat this process until you find a valid pair.
Brute force ignores the ordering and simply checks every possible pair.
For each index i, we look at every index j > i and check whether their sum equals the target.
This approach is easy to understand but inefficient because it tries all combinations without using the sorted property.
i from 0 to n - 1.i, loop through index j from i + 1 to n - 1.numbers[i] + numbers[j] equals the target:[i + 1, j + 1] (1-indexed as required by the problem).Because the array is already sorted, we don’t need to check every pair.
For each number at index i, we know exactly what value we need to find:target - numbers[i].
Since the array is sorted, we can efficiently search for this value using binary search instead of scanning linearly.
This reduces the inner search from O(n) to O(log n), making the solution much faster.
i from 0 to n - 1.numbers[i], compute the needed complement:tmp = target - numbers[i]i + 1 to the end:numbers[mid] == tmp, return [i + 1, mid + 1]numbers[mid] < tmp, search the right halfclass Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
for i in range(len(numbers)):
l, r = i + 1, len(numbers) - 1
tmp = target - numbers[i]
while l <= r:
mid = l + (r - l)//2
if numbers[mid] == tmp:
return [i + 1, mid + 1]
elif numbers[mid] < tmp:
l = mid + 1
else:
r = mid - 1
return []Even though the array is sorted, we can still use a hash map to solve the problem efficiently.
As we scan through the list, we compute the needed complement for each number.
If that complement has already been seen earlier (stored in the hash map), then we have found the required pair.
Otherwise, we store the current number with its (1-indexed) position.
mp that maps numbers to their 1-indexed positions.i from 0 to n - 1:tmp = target - numbers[i]tmp exists in mp, return [mp[tmp], i + 1]mp[numbers[i]] = i + 1Because the array is sorted, we can use two pointers to adjust the sum efficiently.
If the current sum is too big, moving the right pointer left makes the sum smaller.
If the sum is too small, moving the left pointer right makes the sum larger.
This lets us quickly close in on the target without checking every pair.
l = 0 (start)r = len(numbers) - 1 (end)l < r:curSum = numbers[l] + numbers[r].curSum > target, move r left to reduce the sum.curSum < target, move l right to increase the sum.curSum == target, return [l + 1, r + 1].The problem explicitly requires 1-indexed positions in the output. A common mistake is returning [i, j] instead of [i + 1, j + 1]. Always double-check the problem requirements for indexing conventions, as returning 0-indexed results will be marked as incorrect.
Since the array is already sorted, the two-pointer approach achieves O(n) time with O(1) space. Using a hash map still works but wastes the sorted property and uses O(n) extra space unnecessarily. While not incorrect, failing to recognize and use the sorted property results in a suboptimal solution.
In the two-pointer approach, when the sum is too large you should move the right pointer left, and when the sum is too small you should move the left pointer right. A common error is moving both pointers in the same direction or moving the wrong pointer, which causes the algorithm to miss the valid pair or loop infinitely.