2Sum无序,2Sum有序;3Sum,Nsum 模板
3Sum和Nsum的关键是增加start位置
package demo;
import java.util.*;
public class NSum {
public static void main(String[] args){
//Scanner sc = new Scanner(System.in);
int[] nums = new int[]{-1,0,1,2,-1,-2,0};
int target = 0;
/*int[] ans = twoSum1(nums,6);
int[] ans = twoSum2(nums,9);
for(int a : ans){
System.out.println(a);
}*/
//ArrayList<ArrayList<Integer>> ans = twoSum3(nums,target);
//ArrayList<ArrayList<Integer>> ans = threeSum(nums,target);
Arrays.sort(nums);
ArrayList<ArrayList<Integer>> ans = nSum(nums,4,0,target);
System.out.println(ans);
}
//nSum 所有不重复结果
//nums 数组; n nSum; start 数组开始位置
static ArrayList<ArrayList<Integer>> nSum(int[] nums, int n, int start, int target){
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
if(n<2||nums.length<n) return res;
if(n==2){
int lo = start, hi = nums.length-1;
while(lo<hi){
int sum = nums[lo] + nums[hi];
int left = nums[lo], right = nums[hi];
if(sum<target) while(lo<hi&&nums[lo]==left) lo++;
if(sum>target) while(lo<hi&&nums[hi]==right) hi--;
if(sum==target){
ArrayList<Integer> cnt = new ArrayList<>();
cnt.add(left);
cnt.add(right);
res.add(cnt);
while(lo<hi&&nums[lo]==left) lo++;
while(lo<hi&&nums[hi]==right) hi--;
}
}
}else {
for(int i=start; i<nums.length; i++){
ArrayList<ArrayList<Integer>> tmp = nSum(nums,n-1,i+1,target-nums[i]);
for(ArrayList<Integer> a : tmp){
a.add(nums[i]);
res.add(a);
}
while(i<nums.length-1&&nums[i]==nums[i+1]) i++;
}
}
return res;
}
//3Sum 所有不重复结果
static ArrayList<ArrayList<Integer>> threeSum(int[] nums, int target){
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for(int i=0; i<nums.length; i++){
ArrayList<ArrayList<Integer>> cnt = twoSum(nums,i+1,target-nums[i]);
for(ArrayList<Integer> a : cnt){
a.add(nums[i]);
res.add(a);
}
while(i<nums.length-1&&nums[i]==nums[i+1]) i++;
}
return res;
}
//2Sum 调用模板
static ArrayList<ArrayList<Integer>> twoSum(int[] nums, int start,int target){
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
int lo = start,hi = nums.length-1;
while (lo<hi){
int sum = nums[lo] + nums[hi];
int left = nums[lo], right = nums[hi];
if(sum<target) while(lo<hi&&nums[lo]==left) lo++;
if(sum>target) while(lo<hi&&nums[hi]==right) hi--;
if(sum==target){
ArrayList<Integer> cnt = new ArrayList<>();
cnt.add(left);
cnt.add(right);
res.add(cnt);
while(lo<hi&&nums[lo]==left) lo++;
while(lo<hi&&nums[hi]==right) hi--;
}
}
return res;
}
//排序2Sum记录所有不重复结果
static ArrayList<ArrayList<Integer>> twoSum3(int[] nums, int target){
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
int lo = 0,hi = nums.length-1;
while (lo<hi){
int sum = nums[lo] + nums[hi];
int left = nums[lo], right = nums[hi];
if(sum<target) while(lo<hi&&nums[lo]==left) lo++;
if(sum>target) while(lo<hi&&nums[hi]==right) hi--;
if(sum==target){
ArrayList<Integer> cnt = new ArrayList<>();
cnt.add(left);
cnt.add(right);
res.add(cnt);
while(lo<hi&&nums[lo]==left) lo++;
while(lo<hi&&nums[hi]==right) hi--;
}
}
return res;
}
//排序2Sum,双指针
static int[] twoSum2(int[] nums, int target){
Arrays.sort(nums);
int lo = 0,hi = nums.length-1;
int[] res = {-1,-1};
while(lo<hi){
int sum = nums[lo] + nums[hi];
if(sum<target) lo++;
if(sum>target) hi--;
if(sum==target){
res[0] = nums[lo];
res[1] = nums[hi];
return res;
}
}
return res;
}
//无序数组2Sum
//可以但存疑,用HashMap存重复的数字为什么可以
static int[] twoSum1(int[] nums, int target){
Map<Integer,Integer> map = new HashMap<>();
for(int i=0; i<nums.length; i++){
map.put(nums[i],i);
}
int[] res = new int[2];
for(int i=0; i<nums.length; i++){
int cnt = target - nums[i];
if(map.containsKey(cnt)&&map.get(cnt)!=i){
res[0] = nums[i];
res[1] = cnt;
}
}
return res;
}
}