LeetCode(001) Two Sum (Java)

本文解析了一道经典的算法题“两数之和”,提供了三种不同的解决方案,包括排序加双指针法、两次遍历哈希表法及单次遍历哈希表法,并讨论了各种方法的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目如下:

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  详细见代码中的bug 注释

2  用这道题目来熟悉了java中常见的comparator ,sort, hash的用法。


我的代码:

一共写了3个版本。

第一个版本,先sort,然后头尾各来一个指针,开始搜寻。

// Solution 1 
//252 ms
public class Solution {
		
		class Element {
			private int value;
			private int index;
			Element(int v, int i) {
				this.value = v;
				this.index = i + 1;
			}
		}
		
	    public int[] twoSum(int[] numbers, int target) {
	    	Element[] e = new Element[numbers.length];
	    	int[] res = new int[2];
	    	
	    	for (int i = 0; i < numbers.length; ++i) {
	    		e[i] = new Element(numbers[i], i);
	    	}
	    	
	    	//NOTE1: compartor的写法格式
	    	Arrays.sort(e, new Comparator<Element> ()  {
	    			public int  compare(Element a, Element b) {
                                        // java使用1, 0, -1来代表大小关系的比较。
	    			        return a.value>b.value?1:(a.value==b.value?0:-1);
	    			}
	    	});
	        int i = 0, j = numbers.length - 1;
	        while (i < j) {
	        	if (e[i].value + e[j].value > target) {
	        		--j;
	        		//BUG1: 注意 j 和 j + 1 比较,不是 j 和 j -1 比较。
	        		while(i < j && j < numbers.length -1 &&  e[j].value == e[j + 1].value) {
	        		    --j;
	        		}
	        	} else if (e[i].value + e[j].value < target) {
	        		++i;
	        		//BUG2: 注意 i 和 i -1  比较,不是 i 和 i + 1 比较。
	        		while (i < j && i > 0 && e[i].value == e[i - 1].value) {
	        		    ++i;    
	        		}
	        	} else {
	        		res[0] = e[i].index;
	        		res[1] = e[j].index;
	        		break;
	        	}
	        }
                //BUG3: The final result should be sorted
	        Arrays.sort(res); 
	        return res;
	    }
	    
	}


第二个版本是使用hashmap来做的。

但是提交发现,有个很容易忽略的case

// Input:    [3,2,4], 6
// Output:    1, 1
// Expected: 2, 3

这里,误以为 6 = 3 + 3。但是其实3 只出现了1次,而不是2次,所以在map里还要注意判断是否重复考虑了元素的相加。

// Solution 2
// swipe the array twice, one for bulding the map, another for searching. Then there might be a trap below
// 常见错误: map 没有考虑区别不合理的重复计算,比如下面的6 = 3 + 3,其实不对。应该被去掉。
// Input:	    [3,2,4], 6
// Output:	    1, 1
// Expected:	2, 3
// 248 ms
public class Solution {
	    public int[] twoSum(int[] numbers, int target) {
	    	int[] result = new int [2];
	    	HashMap<Integer, Integer> map = new HashMap<Integer, Integer> ();
	    	for (int i = 0; i < numbers.length; ++i) {
	    		map.put(numbers[i], i + 1);
	    	}
	    	for (int i = 0; i < numbers.length; ++i) {
	    		if( map.containsKey(target - numbers[i]) && map.get(target - numbers[i]) != i + 1) {
	    			result[0] = i + 1;
	    			result[1] = map.get(target - numbers[i]);
	    			break;
	    		} 
	    	}
	    	Arrays.sort(result);
	    	return result;
	    }
}

上面这个版本扫描了原数组两次,其实只要稍微改动一下,就可以只扫描原数组一次了。

// solution 3
// 294 ms
public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        HashMap<Integer, Integer> hashmap = new HashMap<Integer, Integer> ();
        int[] result = new int[2];
        for (int i = 0; i < numbers.length; ++i) {
            if (hashmap.containsKey(target - numbers[i])) {
                result[0] = i + 1;
                result[1] = hashmap.get(target - numbers[i]);
                break;
            } else {
                hashmap.put(numbers[i], i + 1);
            }
        }
        Arrays.sort(result);
        return result;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值