您的位置:首页 > 其它

Leetcode 1. Two Sum & 15. 3Sum & 16. 3Sum Closest & 18. 4Sum

2016-03-07 13:49 405 查看


1. Two Sum

Total Accepted: 196496 Total
Submissions: 907244 Difficulty: Medium

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.

Method大体思想就一个,HashMap。

版本1,自己写的,因为<key,value> key应该唯一,因此key是index,value是值。

public class Solution { // 182ms
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
HashMap<Integer,Integer> hmap = new HashMap<Integer,Integer>();
if (nums == null || nums.length<3) return res;

for (int i = 0; i<nums.length; i++)
{
if (hmap.containsValue(target-nums[i]))
{
res[1] = i;
for (int key : hmap.keySet())
{
if (hmap.get(key)==target-nums[i])
{
res[0] = key;
return res;
}
}
}else
{
hmap.put(i,nums[i]);
}
}
return res;
}
}


必须不服,上网找来版本2:

public class Solution {
public int[] twoSum(int[] numbers, int target) {

if(numbers.length>=2)
{
HashMap<Integer,Integer> h = new HashMap<Integer,Integer>();
for(int i=0; i<numbers.length; i++){
if(!h.isEmpty() && h.containsKey(target-numbers[i]))
{
int[] k = {h.get(target-numbers[i]),i};
return k;
}

h.put(numbers[i],i);
}
}

int[] k = {-1,-1};
return k;
}
}

运行时间是7ms。。仔细一看,我说哥们,你这代码key, value反过来了啊,这不符合map定义啊!!!后来一

看题,只有一个解,那意思是就算元素重复了也OK,只要输出一个解就行。

于是把自己之前的代码key, value交换了一下,6ms:

public class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
HashMap<Integer,Integer> hmap = new HashMap<Integer,Integer>();
if (nums == null || nums.length<3) return res;

for (int i = 0; i<nums.length; i++)
{
if (hmap.containsKey(target-nums[i]))
{
res[1] = i;
res[0] = hmap.get(target-nums[i]);
return res;
}else
{
hmap.put(nums[i],i);
}
}
return res;



15. 3Sum

Total Accepted: 105161 Total
Submissions: 570987 Difficulty: Medium

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:

Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
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)

3sum网上解法大同小异。先取一个点,然后进行2sum,因为要去重,所以移动指针的时候需要判定当前

元素和之前所指的元素是否相同,如果相同则继续移动。

三个指针就有3个地方需要判断去重。

public class Solution {  //8ms
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
int len=nums.length;
if(len<3)return res;
Arrays.sort(nums);
for(int i=0;i<len;i++){
if(nums[i]>0)break;
if(i>0 && nums[i]==nums[i-1])continue;
int begin=i+1,end=len-1;
while(begin<end){
int sum=nums[i]+nums[begin]+nums[end];
if(sum==0){
List<Integer> list = new ArrayList<Integer>();
list.add(nums[i]);list.add(nums[begin]);list.add(nums[end]);
res.add(list);
begin++;end--;
while(begin<end && nums[begin]==nums[begin-1])begin++;
while(begin<end && nums[end]==nums[end+1])end--;
}else if(sum>0)end--;
else begin++;
}
}
return res;
}
}





16. 3Sum Closest

Total Accepted: 69789 Total
Submissions: 244144 Difficulty: Medium

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


用一个变量代表目前的最小diff,如果sum比当前diff小,则更新,否则继续循环,最后输出最小diff。

版本一,自己写的:

public class Solution { //12ms
public int threeSumClosest(int[] nums, int target) {
int diff = Integer.MAX_VALUE;
int sum;int begin;int end;int res=-1;
Arrays.sort(nums);
for (int i=0;i<nums.length;i++)
{
begin=i+1;end=nums.length-1;
while(begin<end)
{
sum = nums[i]+ nums[begin]+nums[end];
if (sum==target) return target;
if(Math.abs(sum-target)<diff)
{
diff=Math.abs(sum-target);
res=sum;
}
if(sum>target) end--;
else begin++;
}
}
return res;
}
}


版本二:

public class Solution {//10ms
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int diff = Integer.MAX_VALUE, closest = 0;
for (int k=0; k<nums.length-2; ++k) {
for (int i=k+1, j=nums.length-1; i<j; ) {
int sum = nums[k] + nums[i] + nums[j];
if (sum == target) { return target; }
else if (sum > target) {
if (sum-target < diff) {
diff = sum-target;
closest = sum;
}
--j;
} else {
if (target-sum < diff) {
diff = target-sum;
closest = sum;
}
++i;
}
}
}
return closest;
}
}



18. 4Sum

Total Accepted: 65299 Total
Submissions: 279841 Difficulty: Medium

Given an array S of n integers, are there elements a, b, c, 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:

Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
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)

方法一:

延续sum系列思想,取第一个点,fix住,然后取第二个点,fix住,之后进行two pointers以前一后直到

相遇,然后移动前两个点,符合条件就输出。

去重方式同3sum。

public class Solution{ //56ms
public static List<List<Integer>> fourSum(int[] nums, int target) {
if(nums==null||nums.length==0)
return new ArrayList<List<Integer>>();
Arrays.sort(nums);
int len=nums.length;
List<List<Integer>> result=new ArrayList<List<Integer>>();
for(int i=0;i<len-3;i++){
if(i>0&&nums[i]==nums[i-1])
continue;
for(int j=i+1;j<len-2;j++){
if(j>i+1&&nums[j]==nums[j-1])
continue;
int sum=target-nums[i]-nums[j],slow=j+1,fast=len-1;
while(slow<fast){
if(nums[slow]+nums[fast]==sum){
List<Integer> tmp=new ArrayList<Integer>();
tmp.add(nums[i]);
tmp.add(nums[j]);
tmp.add(nums[slow]);
tmp.add(nums[fast]);
result.add(tmp);
while(slow<fast&&nums[slow]==nums[slow+1])
slow++;
slow++;
while(fast>slow&&nums[fast]==nums[fast-1])
fast--;
fast--;
}
else if(nums[slow]+nums[fast]>sum)
fast--;
else
slow++;
}
}
}
return result;
}
}


方法二:可以看到方法一用了56MS,因为有很多不用判断的情况,下面这个版本很巧妙,固定了首尾

两个元素,因为这两个元素可以帮忙判断是否需要跳过当前情况。如果首元素大于target/4,则因为元

素递增,则再往后的case不需要考虑了;如果尾元素小于targer/4,则因为元素递增,则再往前的

case不用考虑。

public class Solution { //11ms
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
Arrays.sort(nums);
int second = 0, third = 0;
for(int i=0, L=nums.length; i<L-3; i++) {
if(nums[i]<<2 > target) return list; // return immediately
for(int j=L-1; j>i+2; j--) {
if(nums[j]<<2 < target) break; // break immediately
int rem = target-nums[i]-nums[j];
int lo = i+1, hi=j-1;
while(lo<hi) {
int sum = nums[lo] + nums[hi];
if(sum>rem) --hi;
else if(sum<rem) ++lo;
else {
list.add(Arrays.asList(nums[i],nums[lo],nums[hi],nums[j]));
while(++lo<=hi && nums[lo-1]==nums[lo]) continue; // avoid duplicate results
while(--hi>=lo && nums[hi]==nums[hi+1]) continue; // avoid duplicate results
}
}
while(j>=1 && nums[j]==nums[j-1]) --j; // skip inner loop
}
while(i<L-1 && nums[i]==nums[i+1]) ++i; // skip outer loop
}
return list;
}
}


至于网上的其他解法,比如backtracking,还有Ksum的通解,博主才leetcode第一遍,时间压力很大,选择

暂时跳过。目前来说选择自己能理解的方法好些。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: