leetcode:两数之和-三数之和-四数之和系列之KSum的总结

leetcode 1 :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 sameelement twice.

Example:

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

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

实现1:暴力破解法

 public int[] twoSum(int[] nums, int target) {
	 int[] ret=new int[2];
	  for(int i=0;i<nums.length;i++){
		  for(int j=i+1;j<nums.length;j++){
			  if(nums[i]+nums[j]==target){
				  ret[0]=i;
				  ret[1]=j;
			  }
		  }
	  }
	return ret;
    }

 

实现2:Hashmap空间换时间

在hashmap中以数的值为key,index为value,每次检测是否有target-值得key,时间o(n) 

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

 

167. Two Sum II - Input array is sorted(返回索引)

本题的扩展题:https://blog.csdn.net/orangefly0214/article/details/89165543

Given an array of integers that is already sorted in ascending order, 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.

Note:

  • Your returned answers (both index1 and index2) are not zero-based.
  • You may assume that each input would have exactly one solution and you may not use the sameelement twice.

Example:

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.

实现1:双指针法

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] res = new int[2];
        int low = 0;
        int high = numbers.length - 1;

        while(low < high){
            if(numbers[low] + numbers[high] < target){
                    low++;
                }else if(numbers[low] + numbers[high] > target){
                    high--;
                }else{
                    res[0] = low + 1;
                    res[1] = high + 1;
                    break;
                }
            }

            return res;
    }
}

 

15. 3Sum(返回满足条件的元素)

https://leetcode.com/problems/3sum/

本题的变形题:https://blog.csdn.net/orangefly0214/article/details/89294752

Given an array nums of n integers, are there elements abc in nums 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.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

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

思路:

1. 对数组进行排序。

2.固定住其中一个数,然后对数组中剩下的数用TwoSum==target的方式解决。(https://blog.csdn.net/orangefly0214/article/details/89165543

3. 因为数组中存在相同的数,为了避免出现相同的答案,需要跳过数组中相同的元素。

import java.util.LinkedList;
import java.util.List;
import java.util.Arrays;
/* 1.对数组元素进行排序。
 * 2.固定住一个数,对后面的元素进行遍历,寻找满足条件的twoSum==target的值(leetcode167)
 * 3.当两数之和满足条件,且存在重复的数时,则跳过重复的数(因为输出的是元素值,重复元素会有重复结果。)*/
public class ThreeSumDemo {
	public List<List<Integer>> threeSum(int[] nums,int target) {
	 Arrays.sort(nums);
	 List<List<Integer>> res=new LinkedList<>();
	 for (int i = 0; i < nums.length-2; i++) {
		 if(i==0||(i>0&&nums[i]!=nums[i-1])){
			 //为什么只需要从固定数的后面开始寻找而不管前面的数呢?因为前面的之前已经遍历过了,
			 //如果存在可行解的话也已经加入到list中了,所以只需要遍历后半截即可
			 int low=i+1,high=nums.length-1,sum=target-nums[i];
			 while(low<high){
				 if(nums[low]+nums[high]==sum){
					//Arrays.asList()可以将多个元素转换为list,不过不能进行插入和删除
					 res.add(Arrays.asList(nums[i],nums[low],nums[high]));
					 while(low<high&&nums[low]==nums[low+1]){
						 low++;
					 }
					 while(low<high&&nums[high]==nums[high-1]){
						 high--;
					 }
					 low++;
					 high--;
				 }else if(nums[low]+nums[high]<sum){
					 low++;
				 }else{
					 high--;
				 }
			 }
		 }
		
	}
	return res;
		
	}
	public static void main(String[] args) {
		ThreeSumDemo tsd=new ThreeSumDemo();
		int[] nums={-1, 0, 1, 2, -1, -4};
		int[] nums2={1,2,3,4,5,6,7,8,9,10,11};
		System.out.println(tsd.threeSum(nums2, 14).toString());
	
	}

}

 

18. 4Sum https://leetcode.com/problems/4sum/

Given an array nums of n integers and an integer target, are there elements abc, and d in numssuch 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.

Example:

Given array nums = [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]
]

思路:

本题解法和2Sum,3Sum的思路是一样的。
 * step1:数组进行排序;
 * step2:二重循环,从头开始遍历,固定其中的2个数,然后再数组中寻找和为target减去这两个数的2Sum。
 * (将问题转换为2Sum问题)

实现:

import java.util.List;
import java.util.Arrays;
import java.util.LinkedList;
public class FourSumDemo {
	public List<List<Integer>> fourSum(int[] nums, int target) {
	List<List<Integer>> res=new LinkedList<>();
	Arrays.sort(nums);
	for (int i = 0; i < nums.length-3; i++) {
		if(i>0&&nums[i]==nums[i-1]){
			continue;
		}
		for (int j = i+1; j < nums.length-2; j++) {
			if(j>1&&nums[j]==nums[j-1]&&j-i>1){
				continue;
			}
			//已经固定好了前个数,在后面的数中进行2Sum
			int low=j+1,high=nums.length-1,sum=target-nums[i]-nums[j];
			while(low<high){
				if(nums[low]+nums[high]==sum){
					res.add(Arrays.asList(nums[i],nums[j],nums[low],nums[high]));
					while(low<high&&nums[low]==nums[low+1]){
						low++;
					}
					while(low<high&&nums[high]==nums[high-1]){
						high--;
					}
					low++;
					high--;
				}else if(nums[low]+nums[high]<sum){
					low++;
				}else{
					high--;
				}
			}
			
		}		
	}
	return res; 
	}
	public static void main(String[] args) {
		FourSumDemo fsd=new FourSumDemo();
		int[] nums={1, 0, -1, 0, -2, 2};
		System.out.println(fsd.fourSum(nums, 0));
	}
}

 

总结:Ksum的题目

通过上面的2Sum,3Sum,4Sum,我们发现大于2时问题最终都转换为2Sum。

那么所有的Ksum问题都可以转换为以下2个问题:

1. 2Sum的问题;

2. 将KSum的问题转换为(K-1)Sum的问题

因此我们可以用递归来解决这个问题,时间复杂度是o(N^(K-1)).

KSum 的实现:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class kSumDemo2 {
 private ArrayList<List<Integer>> kSum(int[] nums, int target, int k, int index) {
	 int len=nums.length;
	 ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
	//2Sum问题
	 if(k == 2) {
		int low = index, high = len - 1;
		while(low < high) {
			 //find a pair
			if(target - nums[low] == nums[high]) {
				List<Integer> temp = new ArrayList<>();
				temp.add(nums[low]);
				temp.add(target-nums[low]);
				 res.add(temp);
				 //若存在重复的数,则跳过
				 while(low<high && nums[low]==nums[low+1]) low++;
				 while(low<high && nums[high-1]==nums[high]) high--;
			   //不重复,找到一对后继续查找
				 low++;
				 high--;
			 //move left bound
			} else if (target - nums[low] > nums[high]) {
				low++;
			 //move right bound
			} else {
				high--;
			}
		}
	 } else{//Ksum问题,转换为2Sum问题
		 for (int i = index; i < len - k + 1; i++) {
			//固定当前的数,将KSum减到K-1Sum
			 ArrayList<List<Integer>> temp = kSum(nums, target - nums[i], k-1, i+1);
			 if(temp != null){
				 //add previous results
				 for (List<Integer> t : temp) {
					 t.add(0, nums[i]);
				 }
				 res.addAll(temp);
			 }
			 while (i < len-1 && nums[i] == nums[i+1]) {
				 //skip duplicated numbers
				 i++;
			 }
		 }
	 }
	 return res;
 }    
public static void main(String[] args) {
	kSumDemo2 ksd=new kSumDemo2();
	int[] nums={1, 0, -1, 0, -2, 2};
	Arrays.sort(nums);
	System.out.println(ksd.kSum(nums, 0, 4, 0));
}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值