算法题(二十八):和为S的两个数

题目描述

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

分析

在数组的头部(H)和尾部(T)开始向内遍历,若H+T小于S,则H肯定不是答案之一,因为不可能有数比T大了;若H+T大于S,则T肯定不是答案之一,因为不可能有数比H小了。而当第一次找到H和T时,这时的H*T也是最小的。

牛客网上解释为:考虑x+y=C(C是常数),x*y的大小。不妨设y>=x,y-x=d>=0,即y=x+d, 2x+d=C, x=(C-d)/2, x*y=x(x+d)=(C-d)(C+d)/4=(C^2-d^2)/4,也就是x*y是一个关于变量d的二次函数,对称轴是y轴,开口向下。d是>=0的,d越大, x*y也就越小。

代码

public class DoubleSum {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr = {1,2,9,10};
		findSum(arr, 11);
	}
	
	public static void findSum(int[] arr, int sum){
		int H = 0;
		int T = arr.length-1;
		while(H<T){
			if(arr[H]+arr[T]==sum){
				System.out.println(H);
				System.out.println(T);
				return;
			}
			while(H<T && arr[H]+arr[T]>sum){
				--T;
			}
			while(H<T && arr[H]+arr[T]<sum){
				++H;
			}
		}
	}

}

输出:0,3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值