leetcode 18. 4Sum KSum的解决办法
来源:互联网 发布:centos ntp服务器配置 编辑:程序博客网 时间:2024/05/16 09:14
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: 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]
]
题意很简单,这里就不多说了。这里做一个总结:
第一种方法是把KSum降低为K-1Sum,然后逐步降低,最后处理2Sum,这个可以通过递归实现,也可以通过循环实现,最后的2Sum是通过双指针遍历得到,但是要注意避免重复元素的计算。这里有一个小细节需要注意:我们要寻找KSum的解,那么数组遍历范围是[0,len-k+1)或者[0,len-k],所以在降低k值的时候要注意遍历范围的计算;
第二种是通过Hash实现,不过这个是针对4Sum的,针对KSum也可以类似处理,不过实现起来有点麻烦。思想主要就是把可能的2Sum之和存放到map中,然后通过双指针遍历map来实现2Sum+2Sum=4Sum。 这个问题的比较麻烦的地方是要注意处理重复的元素,因为index可能出现重复,index对应的value重复问题,可以在代码中看出,这个处理比较麻烦。这仅仅是4Sum就这么麻烦,要是针对KSum,要是使用Hash实现,那么处理的就更加麻烦了。
综合来说,我建议使用第一种方法,建议循环实现。
建议和这一道题leetcode 454. 4Sum II 一起学习
import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Set;public class Solution { /* * 通过吧KSum降低为K-1Sum,然后逐步降低,最后处理2Sum * * */ public List<List<Integer>> fourSumBBBB(int[] nums, int target) { Arrays.sort(nums); return kSum(nums, target, 3); } public List<List<Integer>> kSum(int[] nums, int target,int kSum) { List<Integer> one=new ArrayList<>(); kSumByDG(kSum, nums, 0, nums.length-kSum+1, target, one); return finResList; } public void kSumByDG(int kSum,int[] nums,int beg ,int end,int target,List<Integer> one) { if(kSum==2) { int allSum=0; for(int i=0;i<one.size();i++) allSum+=one.get(i); int left=beg,right=end; while(left < right) { int ssum = allSum + nums[left]+nums[right]; if(ssum==target) { List<Integer> tmp = new ArrayList<>(one); tmp.add(nums[left]); tmp.add(nums[right]); finResList.add(tmp); while(left < right && nums[left]==nums[left+1]) left++; while(left < right && nums[right]==nums[right-1]) right--; left++; right--; }else if(ssum < target) left++; else right--; } return ; }else { for(int i=beg;i<end;i++) { while(i!=beg && nums[i]==nums[i-1]) continue; if( i+1 < end+1) { one.add(nums[i]); kSumByDG(kSum-1, nums, i+1, end+1, target, one); one.remove(one.size()-1); } } } } /* * 通过循环,来实现,和上面通过递归实现的本质是一样的。 * */ public List<List<Integer>> fourSum(int[] nums, int target) { List<List<Integer>> finResList=new ArrayList<>(); if(nums==null ||nums.length<4) return finResList; 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!=i+1 && nums[j]==nums[j-1]) continue; int beg=j+1; int end=nums.length-1; while(beg < end) { int sum = nums[i] + nums[j] + nums[beg] + nums[end]; if(sum==target) { List<Integer> t = new ArrayList<Integer>(); t.add(nums[i]); t.add(nums[j]); t.add(nums[beg]); t.add(nums[end]); finResList.add(t); while(beg<end && nums[beg+1]==nums[beg]) beg++; while(beg<end && nums[end-1]==nums[end]) end--; beg++; end--; }else if(sum < target) beg++; else end--; } } } return finResList; } HashMap<Integer, List<List<Integer>>> map=new HashMap<>(); List<List<Integer>> finResList=new ArrayList<>(); List<List<Integer>> finIndexList=new ArrayList<>(); //使用hash需靠考虑的细节实在是太多了,下面的方法并不能覆盖所有情况 public List<List<Integer>> fourSumWithHash(int[] nums, int target) { Arrays.sort(nums); if(nums==null || nums.length<4) return finResList; else if(nums.length==4) { int sum=0; List<Integer> tt=new ArrayList<>(); for(int i=0;i<nums.length;i++) { tt.add(nums[i]); sum+=nums[i]; } if(sum==target) finResList.add(tt); return finResList; } for(int i=0;i<nums.length;i++) { for (int j = i+1; j < nums.length; j++) { int sum=nums[i] + nums[j]; List<Integer> tmp=new ArrayList<>(); tmp.add(i); tmp.add(j); tmp.add(nums[i]); tmp.add(nums[j]); List<List<Integer>> res=map.get(sum); if(res==null) { res=new ArrayList<>(); map.put(sum, res); } map.get(sum).add(tmp); } } List<Integer> key=new ArrayList<>(map.keySet()); key.sort(null); int left=0,right=key.size()-1; while(left <= right) { int sum=key.get(left) + key.get(right); if(sum==target) { List<List<Integer>> res1=map.get(key.get(left)); List<List<Integer>> res2=map.get(key.get(right)); for (int j = 0; j < res1.size(); j++) { for (int k = 0; k < res2.size(); k++) { AddOne(res1.get(j),res2.get(k)); } } left++; right--; }else if(sum < target) left++; else right--; } return finResList; } public void AddOne(List<Integer> a,List<Integer> b) { Set<Integer> set=new HashSet<Integer>(); set.add(a.get(0)); set.add(a.get(1)); set.add(b.get(0)); set.add(b.get(1)); if(set.size()<4) return ; List<Integer> index=new ArrayList<>(set); index.sort(null); boolean need=true; /* * 重复添加问题的解决,先判断index的重复 * */ for(int i=0;i<finIndexList.size();i++) { List<Integer> tt=finIndexList.get(i); if(tt.get(0)==index.get(0) && tt.get(1)==index.get(1) && tt.get(2)==index.get(2) && tt.get(3)==index.get(3)) { need=false; break; } } if(need) { List<Integer> res=new ArrayList<>(); res.add(a.get(2)); res.add(a.get(3)); res.add(b.get(2)); res.add(b.get(3)); res.sort(null); boolean sub=true; //index不重复的前提下考虑,具体数值的重复 for(int i=0;i<finResList.size();i++) { List<Integer> tt=finResList.get(i); if(tt.get(0)==res.get(0) && tt.get(1)==res.get(1) && tt.get(2)==res.get(2) && tt.get(3)==res.get(3)) { sub=false; break; } } if(sub) finResList.add(res); } } public static void main(String[] args) { Solution so=new Solution(); int []nums={-2,-1,0,0,1,2}; System.out.println(so.fourSum(nums, 0)); }}
下面是KSum的C++实现,主要是通过把K Sum 降低为k-1 Sum来做的,就是一个递归解决问题。
代码如下:
#include <iostream>#include <vector>#include <algorithm>using namespace std;class Solution {public: vector<vector<int>> res; vector<vector<int>> fourSum(vector<int>& nums, int target) { sort(nums.begin(),nums.end()); kSum(nums, target, 4); return res; } void kSum(vector<int> nums, int target,int kSum) { vector<int> one; kSumByDG(kSum, nums, 0, nums.size() + 1 - kSum, target, one); } void kSumByDG(int kSum, vector<int> nums, int beg, int end, int target, vector<int>& one) { if (kSum == 2) { int allSum = 0; for (int k = 0; k < one.size(); k++) allSum += one[k]; int i = beg, j = end; while (i < j) { int sum = allSum + nums[i] + nums[j]; if (sum == target) { vector<int> a=one; a.push_back(nums[i]); a.push_back(nums[j]); res.push_back(a); while (i < j && nums[i] == nums[i + 1]) i++; while (i < j && nums[j] == nums[j - 1]) j--; i++; j--; } else if (sum < target) i++; else j--; } } else { for (int i = beg; i < end; i++) { if (i != beg && nums[i] == nums[i - 1]) continue; one.push_back(nums[i]); kSumByDG(kSum - 1, nums, i + 1, end + 1, target, one); one.erase(one.end()-1); } } }};
- leetcode 18. 4Sum KSum的解决办法
- leetcode-18 4Sum(kSum)
- leetcode 18: 4Sum (KSum)
- LeetCode(3 Sum, 4sum, ksum)
- [C++]LeetCode: 71 4Sum && kSum总结
- LeetCode-18-4Sum(证明/KSum)-Medium
- leetcode - 3Sum ( kSum )
- leetcode--ksum问题--3sum
- 【Ksum】求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)
- [Leetcode][求和问题2Sum/3Sum/4Sum/KSum]相关题目汇总/分析/总结
- leetcode - 3Sum Closest (kSum Closest)
- LeetCode-15-3Sum(证明/KSum)-Medium
- LeetCode相关的KSum总结
- LeetCode 求和问题总结(2sum,3sum,ksum)
- LeetCode-16-3Sum Closest(证明/KSum)-Medium
- 15.leetcode 3Sum(medium)[排序 查找 Ksum问题]
- LeetCode总结 -- kSum篇
- LeetCode总结 -- kSum篇
- 《SpringBoot学习-入门》
- 一次软件测试的电话面试分享
- 关于snprintf函数
- Java 多线程守护线程
- hashmap面试题总结
- leetcode 18. 4Sum KSum的解决办法
- SpringBoot学习笔记(九):后台接口返回JsonString乱码问题
- oracle数据库查询正在执行的sql,并杀应用会话
- ssm框架发送邮件
- 拖拽进度条组件API
- 欢迎使用CSDN-markdown编辑器
- SNMP 原理详解
- bug描述的标准
- IE7,IE8浏览器纯CSS实现正圆角效果