Day35:和为S的两个数字

122 阅读3分钟

描述

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

题源:和为S的两个数字_牛客题霸_牛客网 (nowcoder.com)

示例1

输入:

[1,2,4,7,11,15],15

复制

返回值:

[4,11]

复制

说明:

返回[4,11]或者[11,4]都是可以的       

示例2

输入:

[1,5,11],10

复制

返回值:

[]

复制

说明:

不存在,返回空数组     

示例3

输入:

[1,2,3,4],5

复制

返回值:

[1,4]

复制

说明:

返回[1,4],[4,1],[2,3],[3,2]都是可以的   

示例4

输入:

[1,2,2,4],4

复制

返回值:

[2,2]
方法一:双指针(扩展思路)

知识点:双指针

双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。

思路:

这道题目还有一个条件是数组是升序序列,在方法一中没有用到。这个条件有什么用?既然数组是有序的,那我们肯定知道和找到一定程度就不找了,我们为什么要从最小的两个数开始相加呢?我们可以用二分法的思路,从中间开始找。 还可以利用Java中的排序在找;

使用双指针指向数组第一个元素和最后一个元素,然后双指针对撞移动,如果两个指针下的和正好等于目标值sum,那我们肯定找到了,如果和小于sum,说明我们需要找到更大的,那只能增加左边的元素,如果和大于sum,说明我们需要找更小的,只能减小右边的元素。

具体做法:

  • step 1:准备左右双指针分别指向数组首尾元素。
  • step 2:如果两个指针下的和正好等于目标值sum,则找到了所求的两个元素。
  • step 3:如果两个指针下的和大于目标值sum,右指针左移;如果两个指针下的和小于目标值sum,左指针右移。
  • step 4:当两指针对撞时,还没有找到,就是数组没有。

图示:

alt

public ArrayList<Integer> FindNumbersWithSum(int [] array, int sum) {
    ArrayList<Integer> arrayList = new ArrayList();
    if (array.length == 0)return arrayList;
    //嵌套循环
    for(int i = 0;i < array.length;i++){
        for (int j = 1; j < array.length;j++){
            int temp = array[i];
            if (temp + array[j] == sum){
                arrayList.add(temp);
                arrayList.add(array[j]);
                return arrayList;
            }
        }
    }
    return arrayList;
}

复杂度分析:

  • 时间复杂度:O(n*n),其中�n为数组长度,左右指针共同遍历一次数组
  • 空间复杂度:O(1),常数个变量,无额外辅助空间