描述
输入一个升序数组 array 和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,返回任意一组即可,如果无法找出这样的数字,返回一个空数组即可。
示例:
- 输入:[1,2,4,7,11,15],15
- 输出:[4,11]
思路1:两两组合
暴力破解,两两组合
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> list = new ArrayList<>();
for(int i = 0; i < array.length - 1; i++) {
int n = sum - array[i];
for(int j = i + 1; j < array.length; j++) {
if(array[j] == n) {
list.add(array[i]);
list.add(array[j]);
return list;
}
}
}
return list;
}
}
思路2:哈希表
可以看到内层循环是为了在剩余数组中找到可以组合的目标值。
因此可以使用Hash表,快速找到目标值。
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> list = new ArrayList<>();
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < array.length; i++) {
map.put(array[i], i);
}
for(int i = 0; i < array.length; i++) {
int n = sum - array[i];
if(map.containsKey(n) && map.get(n) != i) {
list.add(array[i]);
list.add(n);
return list;
}
}
return list;
}
}
思路3:二分法
由于是升序数组,因此可以用二分法在剩余数组中查找可以组合的目标值。
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> list = new ArrayList<>();
for(int i = 0; i < array.length - 1; i++) {
int n = sum - array[i];
int left = i + 1;
int right = array.length - 1;
while(left <= right) {
int mid = left + right >> 1;
if(array[mid] < n) {
left = mid + 1;
} else if(array[mid] > n) {
right = mid - 1;
} else {
list.add(array[i]);
list.add(array[mid]);
return list;
}
}
}
return list;
}
}
思路4:双指针
双指针分别从前后开始查找,两两组合。由于是升序数组
- 假设
array[i]+array[j]>sum
,i++和只会越来越大,因此只能j-- - 假设
array[i]+array[j]<sum
,j--和只会越来越小,因此只能i++
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> list = new ArrayList<>();
int i = 0;
int j = array.length - 1;
while(i < j) {
if(array[i] + array[j] == sum) {
list.add(array[i]);
list.add(array[j]);
return list;
} else if(array[i] + array[j] > sum) {
j--;
} else {
i++;
}
}
return list;
}
}