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.

Example:

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

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

UPDATE (2016/2/13):
The return format had been changed to zero-based indices. Please read the above updated description carefully.


【问题分析】

kSUM系列的问题有好多个,如下:

我们对这几个题目分别分析并进行总结。

【思路】

1. Two Sum

解决这个问题可以直接利用两层循环对数组进行遍历,这样的时间复杂度为O(N2)。一个巧妙的办法是利用java中的HashMap来解决这个问题,代码如下:

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

由于HashMap的查询效率很高,HashMap的一些操作技巧:http://jiangzhenghua.iteye.com/blog/1196391

2. Two Sum II - Input array is sorted

这个two sum问题中,数组中的元素是已经排序的,我们从数组的头和尾向数组中间靠拢,如果头尾元素相加大于target,则尾指针向前移动一步,如果小于target,则头指针向后移动一步,直到两指针相遇或者相加结果为target。示例如下:[2,3,4,5] target = 7

思路很简单,代码如下:

 public class Solution {
public int[] twoSum(int[] numbers, int target) {
int[] result = new int[2];
if(numbers == null || numbers.length < 2) return result; int left = 0, right = numbers.length-1;
while(left < right){
int cur = numbers[left] + numbers[right];
if(cur == target){
result[0] = left+1;
result[1] = right+1;
return result;
}
else if(cur < target){
left++;
}
else{
right--;
}
}
return result;
}
}

可见,排序后的two sum效率还是很高的。

3. Three sum

The idea is to sort an input array and then run through all indices of a possible first element of a triplet. For each possible first element we make a standard bi-directional 2Sum sweep of the remaining part of the array. Also we want to skip equal elements to avoid duplicates in the answer without making a set or smth like that.

结合two sum和Two Sum II - Input array is sorted我们可以比较好解决这个问题。上面这段话的思路是:先对数组进行排序,然后遍历排序后数组,把每一个元素当做三元组的开始元素,剩下的两个元素的查找和Two Sum II是相同的。在这个过程中需要注意的就是去重,一些重复出现的元素要跳过。代码如下:

 public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result = new LinkedList<>();
for(int i = 0; i < nums.length-2; i++){
if(i == 0 || (i>0 && nums[i] != nums[i-1])){
int target = 0 - nums[i];
int left = i + 1;
int right = nums.length - 1;
while(left < right){
if(nums[left] + nums[right] == target){
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
while(left < right && nums[left] == nums[left+1]) left++;
while(left < right && nums[right] == nums[right-1]) right--;
left++; right--;
}
else if (nums[left] + nums[right] < target)
left ++;
else right--;
}
}
}
return result;
}
}

4. 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).

这个题目在3sum的基础上做了一点变化,要在所有2元组中找到与目标值最接近的三元组的和。我的思路和上一个题目类似,先对数组进行排序,然后在遍历过程中如果发现了更接近的元组的和,则更新最接近的值。如果发现了和值有和目标值相等的,则直接返回目标值。代码如下:

 public class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int closest = nums[0]+nums[1]+nums[2];
for(int i = 0; i < nums.length-2; i++){
int left = i+1, right = nums.length-1;
while(left < right){
int cur = nums[i] + nums[left] + nums[right];
if(cur == target) return cur;
else if(cur > target) right--;
else left++;
if(Math.abs(cur-target) < Math.abs(closest-target))
closest = cur;
}
}
return closest;
}
}

5. 4sum

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note: The solution set must not contain duplicate quadruplets.

For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.

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

这个问题的解决可以借鉴3 sum的思路,只要在3sum外层再增加一层循环即可,代码如下:

 public class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> result = new LinkedList<>();
for(int i = 0; i < nums.length-3; i++){
if(i == 0 || (i>0 && nums[i] != nums[i-1])){
int curtarget1 = target - nums[i];
for(int j = i+1; j < nums.length-2; j++){
if(j == i+1 || (j>i+1 && nums[j] != nums[j-1])){
int curtarget2 = curtarget1 - nums[j];
int left = j + 1;
int right = nums.length - 1;
while(left < right){
if(nums[left] + nums[right] == curtarget2){
result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while(left < right && nums[left] == nums[left+1]) left++;
while(left < right && nums[right] == nums[right-1]) right--;
left++; right--;
}
else if (nums[left] + nums[right] < curtarget2)
left ++;
else right--;
}
}
}
}
}
return result;
}
}

自此,这几个解锁的N sum的题目就做完了,这种题目用回溯法适合不适合呢?

另外需要注意在求解的时候要去掉重复的解,如果排序后的元素是a,b,c,d,求解过程如果选定的元素和上一个选定的元素是相同的,则可以直接跳过该元素。至于为什么是这样,大家可以思考一下。

LeetCode OJ 1. Two Sum的更多相关文章

  1. 【LeetCode OJ】Path Sum II

    Problem Link: http://oj.leetcode.com/problems/path-sum-ii/ The basic idea here is same to that of Pa ...

  2. 【LeetCode OJ】Path Sum

    Problem Link: http://oj.leetcode.com/problems/path-sum/ One solution is to BFS the tree from the roo ...

  3. LeetCode OJ 112. Path Sum

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

  4. LeetCode OJ 40. Combination Sum II

    Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...

  5. LeetCode OJ 113. Path Sum II

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

  6. LeetCode OJ:Range Sum Query 2D - Immutable(区域和2D版本)

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  7. LeetCode OJ:Range Sum Query - Immutable(区域和)

    Given nums = [-2, 0, 3, -5, 2, -1] sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0, 5) -&g ...

  8. LeetCode OJ:Three Sum(三数之和)

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  9. LeetCode OJ:Path Sum II(路径和II)

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

随机推荐

  1. 诡异的数学,数字问题 - leetcode

    134. Gas Station 那么这题包含两个问题: 1. 能否在环上绕一圈? 2. 如果能,这个起点在哪里? 第一个问题,很简单,我对diff数组做个加和就好了,leftGas = ∑diff[ ...

  2. Android Studio新手

    目标:Android Studio新手–>下载安装配置–>零基础入门–>基本使用–>调试技能–>构建项目基础–>使用AS应对常规应用开发 AS简介 经过2年时间的研 ...

  3. 绿色版的mysql安装配置方式

    解压下载好的压缩包 copy 一份my-default.ini改名字为my.ini为mysql的配置文件 打开my.ini 修改配置文件 默认的原版文件为 # For advice on how to ...

  4. 关于git提交、还原使用

    1.本地修改,未提交到本地仓库,想要恢复到修改前 右键这个文件-team-show local hostory -找到某一版本-右键-get Contents 即可恢复到某一版本 2. 命令:git ...

  5. 阿里云-对象储存OSS

    最近 需要搞一个阿里云的文件上传 手机端主要做了图片上传 pod安装:pod 'AliyunOSSiOS', '~> 2.5.2' 主要就是需要四个参数:accessKey secretKey  ...

  6. iPhone doesn’t support any of GongShangJ.app’s architectures. You can add iPhone’s armv7s architectu

    iPhone doesn't support any of GongShangJ.app's architectures. You can add iPhone's armv7s architectu

  7. Debian7安装php5.5/5.6

    ### 1 添加源 echo "deb http://packages.dotdeb.org wheezy-php56 all" >> /etc/apt/sources ...

  8. isset()和empty()的区别

    form表单的数据提交过来 如果用isset() if(isset($_GET)){ .....} '' '0' 0 返回 true 不够严谨 empty() '' '0' 0 显示返回false 比 ...

  9. Hiver 操作 MySQL 导致锁表

    Hadoop 搬迁到新集群后,操作主库 MySQL 导致了锁表...sad 具体锁表时间点  : 2016-1-14 14:31  到   2016-1-14 14:36 之间 在 oradba 的 ...

  10. linux重要目录说明

    1 home :root用户的home 目录是root,普通用户的home 目录是/home,users/(不要随便使用root权限,小白容易改错东西哒) 2 bin:常用可执行文件:/bin./us ...