描述
输入一个升序数组 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:当两指针对撞时,还没有找到,就是数组没有。
图示:
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),常数个变量,无额外辅助空间