{x}
blog image

Two Sum II - Input Array Is Sorted

Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number. Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length.

Return the indices of the two numbers, index1 and index2, added by one as an integer array [index1, index2] of length 2.

The tests are generated such that there is exactly one solution. You may not use the same element twice.

Your solution must use only constant extra space.

 

Example 1:

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore, index1 = 1, index2 = 2. We return [1, 2].

Example 2:

Input: numbers = [2,3,4], target = 6
Output: [1,3]
Explanation: The sum of 2 and 4 is 6. Therefore index1 = 1, index2 = 3. We return [1, 3].

Example 3:

Input: numbers = [-1,0], target = -1
Output: [1,2]
Explanation: The sum of -1 and 0 is -1. Therefore index1 = 1, index2 = 2. We return [1, 2].

 

Constraints:

  • 2 <= numbers.length <= 3 * 104
  • -1000 <= numbers[i] <= 1000
  • numbers is sorted in non-decreasing order.
  • -1000 <= target <= 1000
  • The tests are generated such that there is exactly one solution.

167. Two Sum II - Input Array Is Sorted

This problem asks to find two numbers within a sorted array that add up to a specific target. The solution must use only constant extra space.

This approach iterates through the array. For each number, it uses binary search to check if the complement (target - number) exists in the remaining portion of the array.

Algorithm:

  1. Iterate: Loop through the array using a single for loop.
  2. Calculate Complement: For each number numbers[i], calculate its complement complement = target - numbers[i].
  3. Binary Search: Perform a binary search on the subarray numbers[i+1:] to find the complement. bisect_left (or lower_bound in C++) is efficient for this.
  4. Check and Return: If the complement is found at index j within the subarray, return [i+1, j+1] (indices are 1-based).

Time Complexity: O(n log n). The outer loop iterates n times, and the binary search takes O(log n) time in each iteration.

Space Complexity: O(1). The algorithm uses only a few variables to store indices and the complement.

Approach 2: Two Pointers

This approach leverages the sorted nature of the input array. It uses two pointers, one at the beginning and one at the end of the array, and moves them towards the middle based on the sum of the numbers they point to.

Algorithm:

  1. Initialization: Initialize two pointers, left at the beginning (index 0) and right at the end (index n-1) of the array.
  2. Sum and Compare: Calculate the sum sum = numbers[left] + numbers[right].
  3. Adjust Pointers:
    • If sum == target, return [left + 1, right + 1] (1-based indices).
    • If sum < target, increment left to consider a larger number.
    • If sum > target, decrement right to consider a smaller number.
  4. Repeat: Continue until left and right cross each other (left >= right).

Time Complexity: O(n). The two pointers move towards the middle, resulting in at most n comparisons.

Space Complexity: O(1). Only a few variables are used.

Code Examples

Here's how the two approaches are implemented in various programming languages:

(Note: The following code snippets omit error handling for brevity. Production code should include checks to handle edge cases like empty input arrays or cases where no solution exists.)

import bisect
 
class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        n = len(numbers)
        for i in range(n):
            complement = target - numbers[i]
            j = bisect.bisect_left(numbers, complement, i + 1)
            if j < n and numbers[j] == complement:
                return [i + 1, j + 1]

Python (Two Pointers)

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        left, right = 0, 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

Similar code can be written in Java, C++, JavaScript, and other languages using the same core logic for both approaches. The two-pointer approach is generally preferred due to its better time complexity.