美文网首页算法与数据结构二叉树之下数据结构和算法分析
剑指Offer-40 有序数组的两数和(首尾逼近法)

剑指Offer-40 有序数组的两数和(首尾逼近法)

作者: 北国雪WRG | 来源:发表于2019-01-18 14:17 被阅读0次

    输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。(对应每个测试案例,输出两个数,小的先输出。)

    • 对于 i + j = sum,当i和j大小越悬殊的的时候 i*j越小,如 i = 1,j=sum-1。
      我们可以根据上面的规律,从数组的两头开始寻找。

    首尾相加法

    1. 用i,j两个指针,分别指向首尾
    2. i从首开始遍历,j从尾开始遍历
    3. 对于每个i,j都需要全部寻找一遍
        public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
            ArrayList<Integer> list = new ArrayList<>();
            for(int i=0;i<array.length;i++){
                for(int j=array.length-1;j>=0;j--){
                    if(array[i] + array[j] == sum){
                        list.add(array[i]);
                        list.add(array[j]);
                        return list;
                    }
                }
            }
            return list;
        }
    

    这里面存在一个问题,如果a[i] + a[j] < sum,j依然要 j--,并继续遍历,那么接下来的运算没有意义了。时间复杂度O(n2)

    首尾逼近法

    这是对上一种方法的改进,核心思想还是从首尾开始找,改变的是通过判断a[i] + a[j]sum的大小关系决定是i改变还是j改变。类似于剪纸的思想。

    • 数列满足递增,设两个头尾两个指针i和j,
    • ai + aj == sum,就是答案(相差越远乘积越小)
    • ai + aj > sum,aj肯定不是答案之一(前面已得出 i 前面的数已是不可能),j --
    • 若ai + aj < sum,ai肯定不是答案之一(前面已得出 j 后面的数已是不可能),i ++
        public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
            ArrayList<Integer> list = new ArrayList<>();
            int i = 0, j = array.length -1;
            while(j >= i){
                int temp = array[i] + array[j];
                if(temp == sum){
                    list.add(array[i]);
                    list.add(array[j]);
                    break;
                }else if(temp > sum){
                    j--;
                }else {
                    i ++;
                }
            }
            return list;
        }
    

    时间复杂度O(n)

    相关文章

      网友评论

        本文标题:剑指Offer-40 有序数组的两数和(首尾逼近法)

        本文链接:https://www.haomeiwen.com/subject/uvlndqtx.html