题目:
在有序数组中找出两个数,使得和为给定的数 S。如果有多对数字的和等于 S,输出两个数的乘积最小的。分析
- 乘积最小的规律是:两个数的差尽可能大。
- 要找两个数字,而且是数组,第一感觉就是双指针的策略
思路
使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。
指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
- 如果两个指针指向元素的和 sum == target,那么这两个元素即为所求。
- 如果 sum > target,移动较大的元素,使 sum 变小一些,positionBig变小一些;
- 如果 sum < target,移动较小的元素,使 sum 变大一些,positionSmall 变大一些;
1.如果 sum > target,移动较大的元素,使 sum 变小一些,为什么不是positionSmall 变小一些,而是positionBig变小一些?
如果positionSmall在首位,是没办法小的,只能positionBig变小
2.同理 如果 sum < target,移动较小的元素,使 sum 变大一些,为什么不是positionBig 变大一些,而是positionSmall 变大一些?
同理,如果positionBig在末尾,是没办法变大,只能positionSmall变大
源码
package org.example.pointer;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 和为 S 的两个数字
* @author Abner G
* @date 2022/5/12 20:18
*/
public class practicePointer01 {
/**
* 题目
* 在有序数组中找出两个数,使得和为给定的数 S。
* 如果有多对数字的和等于 S,输出两个数的乘积最小的
* https://github.com/CyC2018/CS-Notes/blob/master/notes/57.1%20%E5%92%8C%E4%B8%BA%20S%20%E7%9A%84%E4%B8%A4%E4%B8%AA%E6%95%B0%E5%AD%97.md
*
*/
public static void main(String[] args) {
int[] test={1, 3, 4,5, 6, 8, 9};
ArrayList<Integer> integers = FindNumbersWithSum(test, 11);
System.out.println(integers);
}
/**
*
* 题点:两个数的乘积最小,说明想要最两边的一组
* 使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。
* 指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
*
* 如果两个指针指向元素的和 sum == target,那么这两个元素即为所求。
* 乘积最小的规律是:两个数的差尽可能大。
* 如果 sum > target,移动较大的元素,使 sum 变小一些,positionBig变小一些;
* 如果 sum < target,移动较小的元素,使 sum 变大一些,positionSmall 变大一些;
*
* 可能死脑经的点:
* 1.如果 sum > target,移动较大的元素,使 sum 变小一些,为什么不是positionSmall 变小一些,而是positionBig变小一些?
* 如果positionSmall在首位,是没办法小的,只能positionBig变小
* 2.同理 如果 sum < target,移动较小的元素,使 sum 变大一些,为什么不是positionBig 变大一些,而是positionSmall 变大一些?
* 同理,如果positionBig在末尾,是没办法变大,只能positionSmall变大
*/
public static ArrayList<Integer> FindNumbersWithSum(int[] nums,int target){
int i=0;
int j=nums.length-1;
while (i<j){
int sum = nums[i] + nums[j];
if (sum==target){
return new ArrayList<>(Arrays.asList(nums[i],nums[j]));
}
if (sum<target){
i++;
}else {
j--;
}
}
return null;
}
}