和为S的两个数

Posted by DH on July 19, 2017

题目

输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

分析

这个题目最容易想到的就是先固定一个数,然后将这个数分别和数组中的每个元素相加,符合要求的加入到list中,然后后移固定的这个数,再从数组开头一次和这个数相加 。这样是可以找出所有的复合要求的组合的。这个算法有两层嵌套,时间复杂度是O(n2)。

还有一种我们称之为“夹逼”的方法,设置两个指针,分别指向数组的第一个元素和最后一个元素。

假如这两个数的和小于S,因为数组是有序的,就将第一个指针后移。

假如这两个数的和大于S,因为数组是有序的,就将最后一个指针前移。

跳出条件是两个指针重合或者第一个指针>后一个指针。

运用这个方法,还有一个好处就是,第一次找到的组合就是相乘后积最小的。

代码

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
       ArrayList <Integer> resultList = new ArrayList<>();
        
        if(array == null || array.length < 2){
            return resultList;
        }
        
        // 指向第一个数的指针
        int first = 0;
        // 指向最后一个数
        int last = array.length -1;
        
        // 假如两个数的和大于sum,后面的数前移,假如两个数的和小于sum,前一个数后移,直到两个数相遇
        int tempSum = 0;
        while(first < last){
            tempSum = array[first] + array[last];
            if(tempSum == sum){// 当前两个数的和为sum,添加到数组
                resultList.add(array[first]);
                resultList.add(array[last]);
                return resultList;//这两个数就是乘积最小的,不用再继续找了
            }else if(tempSum < sum){
                // 和小于sum,前一个数后移
                first++;
            }else{
                last--;
            }
            
        }
        return resultList;
    }
}