Two Sum VII

update Mar 5, 2021

Given an array of integers that is already sorted in ascending absolute order, find two numbers so that the sum of them equals a specific number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Note: the subscript of the array starts with 0

You are not allowed to sort this array.

Example

Input: 
[0,-1,2,-3,4]
1
Output: [[1,2],[3,4]]
Explanation: nums[1] + nums[2] = -1 + 2 = 1, nums[3] + nums[4] = -3 + 4 = 1
You can return [[3,4],[1,2]], the system will automatically help you sort it to [[1,2],[3,4]]. But [[2,1],[3,4]] is invaild.

Challenge

O(n) time complexity and O(1) extra space

Notice

  • It is guaranteed that all numbers in thenumsnumsnums is distinct.

  • The length ofnumsnumsnums is ≤100000.

  • The number in nums is ≤10e9.

Basic Idea

这道题目比较特殊的地方在于数组是按照绝对值排序,也就是说可能会出现正负交错的情况。如果是升序排列,我们可以使用双指针从最小值与最大值出发,O(N) 时间即可找到所有满足条件的pair。而对于这里的情况,由于不是简单的排序,我们没办法直接使用双指针,但是我们发现可以按照两正数,两负数,一正一负分组处理,对于每一组,我们可以做到使用双指针O(N)时间找到所有满足条件的pair。

Java Code

public class Solution {

    public List<List<Integer>> twoSumVII(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        int left = 0, right = nums.length - 1;
        // ab 均大于等于0
        while (left < right) {
            while (left < nums.length && nums[left] < 0) left++;
            while (right >= 0 && nums[right] < 0) right--;
            if (left >= right) break;
            if (nums[left] + nums[right] == target) {
                res.add(Arrays.asList(left, right));
                left++;
                right--;
            } else if (nums[left] + nums[right] < target) {
                left++;
            } else {
                right--;
            }
        }
        // ab 均小于0
        left = 0; right = nums.length - 1;
        while (left < right) {
            while (left < nums.length && nums[left] >= 0) left++;
            while (right >= 0 && nums[right] >= 0) right--;
            if (left >= right) break;
            if (nums[left] + nums[right] == target) {
                res.add(Arrays.asList(left, right));
                left++;
                right--;
            } else if (nums[left] + nums[right] < target) {
                right--;
            } else {
                left++;
            }
        }
        // a < 0, b > 0, 同时从右边开始,保证从最小负数以及最大正数开始
        left = nums.length - 1; right = nums.length - 1;
        while (left >= 0 && right >= 0) {
            while (left >= 0 && nums[left] >= 0) left--;
            while (right >= 0 && nums[right] <= 0) right--;
            if (left < 0 || right < 0) break;
            if (nums[left] + nums[right] == target) {
                int[] arr = new int[]{left, right};
                Arrays.sort(arr);
                List<Integer> list = new ArrayList<>();
                list.add(arr[0]);
                list.add(arr[1]);
                res.add(list);
                left--;
                right--;
            } else if (nums[left] + nums[right] < target) {
                left--;
            } else {
                right--;
            }
        }
        return res;
    }
}

Last updated