题目链接

题目描述

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

示例

  1. 输入:
  2. {1,2,3,4,10,11,12,13} 14
  3. 输出:
  4. {1,13}

解题思路

  1. 二分查找的思想
  2. 定义首尾的两个指针,一个指针指向元素较小的值,一个指针指向元素较大的值。
    • 指向较小元素的指针从头向尾遍历,
    • 指向较大元素的指针从尾向头遍历。
  • 如果两个指针指向元素的和 sum == target ,判断乘积大小。用变量保存小的两个数字
  • 如果 sum > target ,移动较大的元素,使 sum 变小一些;
  • 如果 sum < target ,移动较小的元素,使 sum 变大一些。

    代码

    1. /*
    2. 二分查找思想
    3. */
    4. public ArrayList<Integer> FindNumbersWithSum(int [] nums,int target) {
    5. // 必须放在第一行定义,因为判断数组为空,或者找不到合适的数字时,需要返回空的ArrayList
    6. ArrayList<Integer> arrlist = new ArrayList<>();
    7. // 判断传入数组为空
    8. if(nums.length==0 || nums==null){
    9. return arrlist;
    10. }
    11. // 定义首尾的两个指针
    12. int start=0,end=nums.length-1;
    13. // 定义用来存放最小乘积
    14. int minMulti = Integer.MAX_VALUE;
    15. // 定义两个变量用来存放最小的两个数
    16. int a=-1,b=-1;
    17. // 开始遍历
    18. while(start < end){
    19. int sum = nums[start] + nums[end];
    20. if(sum == target){
    21. int multi = nums[start] * nums[end];
    22. if(multi < minMulti){
    23. a = nums[start];
    24. b = nums[end];
    25. minMulti = multi;
    26. }
    27. // 两端同时收缩
    28. start++;
    29. end--;
    30. }
    31. // 右侧收缩
    32. else if(sum > target){
    33. end--;
    34. }
    35. // 左侧收缩
    36. else if(sum < target){
    37. start++;
    38. }
    39. }
    40. // 数组中没有找到合适的数字,返回初始定义的空ArrayList
    41. if(a==-1 || b==-1){
    42. return arrlist;
    43. }
    44. arrlist.add(a);
    45. arrlist.add(b);
    46. return arrlist;
    47. }