描述

输入一个升序数组 array 和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,返回任意一组即可,如果无法找出这样的数字,返回一个空数组即可。

示例:

  • 输入:[1,2,4,7,11,15],15
  • 输出:[4,11]

思路1:两两组合

暴力破解,两两组合

public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        for(int i = 0; i < array.length - 1; i++) {
            int n = sum - array[i];
            for(int j = i + 1; j < array.length; j++) {
                if(array[j] == n) {
                    list.add(array[i]);
                    list.add(array[j]);
                    return list;
                }
            }
        }
        return list;
    }
}

思路2:哈希表

可以看到内层循环是为了在剩余数组中找到可以组合的目标值。

因此可以使用Hash表,快速找到目标值。

public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < array.length; i++) {
            map.put(array[i], i);
        }
        for(int i = 0; i < array.length; i++) {
            int n = sum - array[i];
            if(map.containsKey(n) && map.get(n) != i) {
                list.add(array[i]);
                list.add(n);
                return list;
            }
        }
        return list;
    }
}

思路3:二分法

由于是升序数组,因此可以用二分法在剩余数组中查找可以组合的目标值。

public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        for(int i = 0; i < array.length - 1; i++) {
            int n = sum - array[i];
            int left = i + 1;
            int right = array.length - 1;
            while(left <= right) {
                int mid = left + right >> 1;
                if(array[mid] < n) {
                    left = mid + 1;
                } else if(array[mid] > n) {
                    right = mid - 1;
                } else {
                    list.add(array[i]);
                    list.add(array[mid]);
                    return list;
                }
            }
        }
        return list;
    }
}

思路4:双指针

双指针分别从前后开始查找,两两组合。由于是升序数组

  1. 假设array[i]+array[j]>sum,i++和只会越来越大,因此只能j--
  2. 假设array[i]+array[j]<sum,j--和只会越来越小,因此只能i++
public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        int i = 0;
        int j = array.length - 1;
        while(i < j) {
            if(array[i] + array[j] == sum) {
                list.add(array[i]);
                list.add(array[j]);
                return list;
            } else if(array[i] + array[j] > sum) {
                j--;
            } else {
                i++;
            }
        }
        return list;
    }
}