寻找和为定值的两个数

/**
 * 输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。
 * 要求时间复杂度是O(N)。如果有多对数字的和等于输入的数字,输出任意一对即可。
 * 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
 * <p>
 * 思路一:直接穷举,从数组中任意选取两个数,判定它们的和是否为输入的那个数字。此举复杂度为O(N^2)
 * <p>
 * 优化:采用二分查找。可以将第二个数字的查找时间复杂度用排序算法优化到O(log N),
 * 这样对于a[i],都要花O(logN)的时间去查找相对应的sum-a[i]是否在数组中,
 * 总的时间复杂度已降为O(N log N),且空间复杂度为O(1)。
 * <p>
 * 思路二:如果a[i]在数组中,那么sum-a[i](a[k])也必然在这个数组中,可以直接寻找a[k]是否在这个数组中,时间复杂度为O(n)
 * 优化:采用hash表对数组进行预处理,可用O(1)的时间复杂度将结果表示出来。但需要经过O(N)时间的预处理,并且用O(N)的空间构造hash表
 * <p>
 * 思路三:相对数组进行排序,时间复杂度为O(N log N),然后用两个指针i,j,各自指向数组的首尾两端,
 * 令i=0,j=n-1,然后i++,j--,逐次判断a[i]+a[j]?=sum
 * 如果某一刻a[i]+a[j] > sum,则要想办法让sum的值减小,所以此刻i不动,j--
 * 如果某一刻a[i]+a[j] < sum,则要想办法让sum的值增大,所以此刻i++,j不动
 * 所以,数组无序的时候,时间复杂度最终为O(N log N + N)=O(N log N)。
 * 如果原数组是有序的,则不需要事先的排序,直接用两指针分别从头和尾向中间扫描,O(N)搞定,且空间复杂度还是O(1)。
 *
 * @author VicterTian
 * @version V1.0
 * @Date 2019/2/16
 */
public class FindTwoNumberForSum {
	/**
	 * 思路二
	 */
	private static void twoSum1(int[] data, int sum) {
		Map<Integer, Integer> hashMap = new HashMap<>(data.length);
		for (int i : data) {
			hashMap.put(i, i);
		}
		for (int i : data) {
			int num = sum - i;
			if (hashMap.containsValue(num)) {
				System.out.println("twoSum1 = " + i + "\t" + num);
				return;
			}
		}
		System.out.println("没有满足条件的值");
	}

	/**
	 * 思路三
	 */
	private static void twoSum2(int[] data, int sum) {
		Arrays.sort(data);
		int begin = 0;
		int end = data.length - 1;
		while (begin < end) {
			int currSum = data[begin] + data[end];
			if (currSum == sum) {
				System.out.println("twoSum2 = " + data[begin] + "\t" + data[end]);
				return;
			} else {
				if (currSum < sum) {
					begin++;
				} else {
					end--;
				}
			}
		}
		System.out.println("没有满足条件的值");
	}

	public static void main(String[] args) {
		int[] data = {-1, 1, -2, 7, 11, 15, 2, -4,};
		twoSum1(data, -3);
		twoSum2(data, 16);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值