剑指offer——和为S的两个数

剑指offer——和为S的两个数

题目描述

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

输出描述:

对应每个测试案例,输出两个数,小的先输出。

我的解答

import java.util.ArrayList;
public class Solution {
    /*常规做法:先求符合两个数之和等于sum的两个数,并且把较小的数存到result数组中;
    * 遍历result数组,找乘积较小的两个数,并将该数输出到resultFinal中,输出。
    */
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> result=new ArrayList<Integer>();
        ArrayList<Integer> resultFinal=new ArrayList<Integer>();
        if(sum<3 || array.length<2){
            return resultFinal;
        }
        //第一步:符合两个数之和等于sum的两个数,并且把较小的数存到result数组中;
        for(int i=0;i<array.length-1;i++){
            int temp=array[i];
            for(int j=i+1;j<array.length;j++){
                if(temp>sum){
                    break;
                }
                if(temp+array[j]==sum){
                    result.add(temp);
                }
            }
        }

        int r=0;
        if(result.size()!=0){
            int small=result.get(0)*(sum-result.get(0));
            for(int k=0;k<result.size();k++){
                if(small>result.get(k)*(sum-result.get(k))){
                    small=result.get(k)*(sum-result.get(k));
                    r=k;
                }
            }
            resultFinal.add(result.get(r));
            resultFinal.add(sum-result.get(r));
        }

        return resultFinal;
    }
}

提升

利用数学知识:按第一数从小到大的排序,第一组的乘积一定最小

通常的想法是先找到满足条件的数组对,然后比较他们的乘积取乘积最小的一组,所以数组必须要遍历完,可是我们通过数学公式推导,发现按第一数从小到大的排序,第一组的乘积一定最小,所以我们只需要从数组两端来查找满足条件的两个数,即为题目要找的数对。

结论证明:

假设:找到两组满足条件的数组对(x,y)、(x+a,y-a),其中(x+y=S, 0 < a < y - x)
x*y-[(x+a)(y-a)]
=x*y-x*y-(y-x)a+a2
=a[a-(y-x)]
因为0 < a < y-x,
所以a-(y-x)<0,
所以a[a-(y-x)]<0
因此(x,y)乘积一定比(x+a,y-a)小

相关算法很简单,可以自行写出。

仔细学习:4 ArrayList中的API

猜你喜欢

转载自blog.csdn.net/yangxingpa/article/details/80601758