LeetCode-(1) Two Sum

 问题地址:https://oj.leetcode.com/problems/two-sum/

问题描述:
Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
思路:
1.因为只有唯一解,所以任意两个元素和为唯一元素。最先想到的是,穷举法,把所有2个元素相加,则得到一个值,如果是Target,则得到解。该方法可行。
判断该方法的复杂度:1+2+3+4+5+...+n= ,即 
考虑有没有更快的方法:
2.通过Target减去数组元素,然后得到被减数,在数组中查找。通过Target减去一个元素,然后在剩余元素中取查找被减数。这样好像更方便,但是其实和上面方法1的复杂度是一样的,即 。
3.空间换时间,在方法2的基础上,如果能把在剩余元素中查找的复杂度从O(n)变为O(1),整体复杂度就会从 变到O(n)。如果把查找变为O(1)呢,当然是Hash表了。因为要返回元素的小标,所以,这里用了hashMap,如果不需要下标,只需要2个元素的值,则可以用HashSet。OK,方法正确。开始实现。
几点注意事项:
1)因为需要小标,所有Map的key是元素的值,Value应该是小标,所以Map应该是 Map<int,int>。但是存在这样的问题,可能存在值相同的元素,这样的话Key相同,之前的下标会被覆盖掉。所以Value应该是一个链表或者数组,下面的code中用了Arraylist。
2)注意小标是从1开始的。
3)要求index1 must be less than index2,所以遍历的时候从0~n遍历。
4)如果是T=X+X这样情况,要避免找到相同的第一个小标,所有要跳过自己。
 Code:
public int[] twoSumNotSame(int[] numbers, int target) {
		int[] a = new int[2];
		HashMap<Integer, ArrayList<Integer>> map = 
new HashMap<Integer, ArrayList<Integer>>(numbers.length);
		for (int i = 0; i < numbers.length; i++) {
			if (map.get(numbers[i]) == null) {
				ArrayList<Integer> list = new ArrayList<Integer>();
				list.add(i);
				map.put(numbers[i], list);
			} else {
				map.get(numbers[i]).add(i);
			}
		}

		ArrayList<Integer> rsList = null;
		int firstIndex = 0;
		for (int i = 0; i < numbers.length; i++) {
			if (map.get(target - numbers[i]) != null) {
				rsList = map.get(target - numbers[i]);
				if (rsList.size() == 1 && rsList.get(0) == i) {
					continue;
				}
				firstIndex = i;
				break;
			}
		}
		int secondIndex = 0;
		for (Integer e : rsList) {
			if (e != firstIndex) {
				secondIndex = e;
				break;
			}
		}
		a[0] = firstIndex + 1;
		a[1] = secondIndex + 1;
		return a;
	}
 UT:
@Test
	public void t1NotEquals() {
		int[] numbers = { 2, 7, 11, 15 };
		int target = 9;
		int[] a = solution.twoSumWithSame(numbers, target);
		Assert.assertEquals(1, a[0]);
		Assert.assertEquals(2, a[1]);

	}

	@Test
	public void t2NotEquals2() {
		int[] numbers = { 20, 4, 11, 15, 3, 5, 9 };
		int target = 13;
		int[] a = solution.twoSumWithSame(numbers, target);
		Assert.assertEquals(2, a[0]);
		Assert.assertEquals(7, a[1]);

	}

	@Test
	public void t3Equals() {
		int[] numbers = { 2, 4, 6, 7 };
		int target = 8;
		int[] a = solution.twoSumWithSame(numbers, target);
		Assert.assertEquals(1, a[0]);
		Assert.assertEquals(3, a[1]);

	}

	@Test
	public void t4Equals2() {
		int[] numbers = { 2, 4, 6 };
		int target = 12;
		int[] a = solution.twoSumWithSame(numbers, target);
		Assert.assertEquals(3, a[0]);
		Assert.assertEquals(3, a[1]);

	}
  思考:
     空间换时间是一种常用的方法,可以通过缓存数据,或者做映射,来降低时间复杂度。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值