题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:对应每个测试案例,输出两个数,小的先输出。
题解一 map
使用map。比如 [1,3,4,11],sum为15。
第一个数为1,15-1=14,需要寻找到值为14这个数,如果有则[1,14]可能是答案。但是map.get(14)不存在,所以将key = 1,value = 14加到map中
1 |
---|
14 |
同理,第二个数为3,15-3=12,需要寻找到值为12这个数,如果有则[3,12]可能是答案。但是map.get(12)不存在,所以将key = 3, value = 12加到map中
1 | 3 |
---|---|
14 | 12 |
[4,11]同理。
1 | 3 | 4 |
---|---|---|
14 | 12 | 11 |
到了第四个数为11的时候,15 - 11 = 4,这个时候map.get(4)的值为11,那么[11,4]有可能是答案,先将乘积44记下来。这个时候数组已经遍历完毕,所以答案就是[4,11]。
1 | 3 | 4 | 11 |
---|---|---|---|
14 | 12 | 11 | 4 |
Java代码
import java.util.ArrayList;
import java.util.HashMap;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
HashMap<Integer,Integer> map = new HashMap<>();
ArrayList<Integer> list = new ArrayList<>();
int plus = 0;
//遍历数组
for(int i = 0; i < array.length; i++){
if(array[i] <= sum){
int other = sum - array[i];
//map的key对应array[i],value对应other
if(map.get(other) != null){
if(list.size() == 0){
list.add(other);
list.add(array[i]);
}else{
if(list.get(0) * list.get(1) >= other * array[i]){
list.clear();
list.add(other);
list.add(array[i]);
}
}
}
else {
map.put(array[i],other);
}
}else break; //因为这是递增排序的数组,如果array[i]大于sum,直接跳出循环
}
return list;
}
}
题解二 双指针
用一个头指针指向数组的第一个a,用一个尾指针指向数组的最后一个b,如果a大于sum,或者a+b > sum,那么尾指针向前移动。如果a + b < sum,那么头指针向前移动。题目要求的是求出和为sum的数如果有多对,返回乘积最小的一对,返回第一对和为sum的数就可以了。记住这是一个递增的数组,最初求出的结果就是符合题目的。
比如:a + b = sum
(a+1)*(b-1) = ab + b - a - 1
a*b = ab
只要b-a >= 1就可以证明第一个对就是题目所要求乘积最小的结果。
import java.util.ArrayList;
import java.util.HashMap;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
int i = 0;
int j = array.length - 1;
ArrayList<Integer> list = new ArrayList<>();
while(i < j){
if(array[i] + array[j] == sum){
list.add(array[i]);
list.add(array[j]);
return list;
}
if(array[j] > sum || array[i] + array[j] > sum) --j;
if(array[i] + array[j] < sum) ++i;
}
return list;
}
}
如有问题希望指出,谢谢。