您的位置:首页 > 其它

leetcode解题笔记:Two sum系列解题思路

2017-03-27 15:06 351 查看
Two Sum

3Sum

3Sum Closest

Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].


解法一

一下能想到的思路就是内外两个循环找和为target的两个数字,这样的复杂度是O(n*n)。

解法二

想到能否用哈希表,每遍历到一个元素num,看target-num是否在hash表中,如果在就得出答案,如果不在就将当前num放入哈希表中。

public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> map= new HashMap<Integer,Integer>();
int[] result = new int[2];
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
result[0]=i;
result[1] = map.get(target-nums[i]);
break;
}else{
map.put(nums[i],i);
}
}
return result;

}


这种解法是O(n)的时间复杂度,但要额外增加O(n)的哈希表存储空间。

解法三

可以换个角度来考虑问题,如果给定的数组是已排序的数组,那么就可以设定lo和hi两个指针,如果这两个数字的和比target要大,那么就lo++,否则hi–。这样排序数组需要O(NlogN),找和的过程需要O(N),但是空间是in-place的。

其实这是
167. Two Sum II - Input array is sorted
抛出的问题。这样我们就不用对数组排序了。

public int[] twoSum(int[] numbers, int target) {
int i = 0;
int j = numbers.length-1;
int[] result = new int[2];
while(j>i){
if(numbers[i]+numbers[j] == target){
result[0] = i+1;
result[1] = j+1;
break;
}else if(numbers[i]+numbers[j] < target){
i++;
}else{
j--;
}
}
return result;
}


时间复杂度为O(N)

3Sum

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]


这次是寻找3个数的和为0的组合。可以接着2Sum解法三的思路来想。首先先对数组排序;然后从头开始每次取一个数作为sum,则此题变成了在后面的数组中寻找两个数其和为-sum,就和上面的过程一样。

这里还要注意一个重复的问题,当我们对数组排序后,重复的数是排列在一起的,此时若已经取过一个解后就不要再取重复的解了。

public List<List<Integer>> threeSum(int[] nums) {
int len = nums.length;
List<List<Integer>> result = new ArrayList<List<Integer>>();
Arrays.sort(nums);
for(int i=0;i<len;i++){
//防止重复解
if(i==0 || nums[i]!=nums[i-1]){
int sum = 0-nums[i];
int lo = i+1;
int hi = len-1;
while(lo<hi){
if(nums[lo]+nums[hi] == sum){
result.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
//防止重复解
while(lo<hi && nums[lo] == nums[lo+1])lo++;
while(lo<hi && nums[hi] == nums[hi-1])hi--;

lo++;
hi--;
}else if(nums[lo]+nums[hi]>sum){
hi--;
}else{
lo++;
}
}
}

}
return result;

}


这种解法的时间复杂度为O(N*N)

3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).


其实和上面的过程一样,只不过是相等比较转换成了差值的比较。

public int threeSumClosest(int[] nums, int target) {
int len = nums.length;
if(len<3) return -1;
Arrays.sort(nums);
int result = nums[0]+nums[1]+nums[2];
for(int i=0;i<len-2;i++){
int lo = i+1;
int hi = len-1;
while(lo<hi){
int sum = nums[i]+nums[lo]+nums[hi];
if(sum == target){
return sum;
}else{
if(Math.abs(sum-target) < Math.abs(target-result)){
result = sum;
}
if(sum>target){
hi--;
}else{
lo++;
}
}
}

}
return result;
}


这种解法的时间复杂度为O(N*N)

总结

可以发现,two sum的解法三是适用于其他变种的,都是在数组已排序的情况下根据当前和与target的比较情况移动指针,其中也要特别注意避免重复解的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode