题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
对应每个测试案例,输出两个数,小的先输出。思路
双指针。本题的关键是数组是递增排序的。那么我们可以定义两个指针,初始化第一个指针指向数组中第一个(最小的)数字,第二个指针指向数组的最后一个(最大的)数字。
- 如果它们的和正好等于输入的S,即满足题意。
- 否则,如果和小于S,我们希望和再大一点,由于数组是递增排序的,我们可以考虑选择较小的数字后面的数字(更大)。
- 如果和大于S,我们选择较大数字前面的数字(更小)。
时间复杂度:只有一个while循环,由于是从两端向中间扫描数组,因此复杂度是O(n)。要优于固定一个数字再对后面数字遍历的方法(这种方法O(n^2))。
代码实现
import java.util.ArrayList; public class Solution { // Note:题目要求输出两个数乘积最小的一对 //不要被题目误导了!乘积最小的那一对就是最先找到的,直接返回即可。 //例如,1,2,3,4,5,6 要求sum为7,那么最外层的1和6的乘积要 小于 内层(2*5、3*4) //用数学分析一波,a + b = sum,那么较小的数字a和较大的数字b满足大小关系: a < sum/2 < b 即a在对称轴左侧 // 设x是较小的那个数,乘积x(7-x)= -x^2+7x,在对称轴左侧是单调递增的,说明x越小乘积越小。 public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) { ArrayList<Integer> res = new ArrayList<>(); if (array == null || array.length == 0) return res; int smallIndex = 0; // 这里small和big记录的都是下标 int bigIndex = array.length - 1; while (smallIndex < bigIndex){ int tempSum = array[smallIndex] + array[bigIndex]; if (tempSum == sum){ res.add(array[smallIndex]); res.add(array[bigIndex]); // 最外层的乘积最小 break; }else if (tempSum < sum){ smallIndex++; }else{//tempSum > sum bigIndex--; } } return res; } }