题目
Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
Example 1:
Input: k = 3, n = 7
Output:
[[1,2,4]]
Example 2:
Input: k = 3, n = 9
Output:
[[1,2,6], [1,3,5], [2,3,4]]
思路一:报超时
combinationSum3(k, n)的结果可以由combinationSum3(k-1, n-i)的结果集中的每种结果加入数字i即可得到,其中i在1~9之间。
其中,我们还涉及到判断结果中是否有重复的数和是否有重复的结果。
实现代码如下:
public class CombinationSum3 {
/*
* k个数的和为n
* */
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
if(k<1||n<1||(k==1&&n>9)){
return res;
}
else if(k==1&&n<=9){
List<Integer> list = new ArrayList<Integer>();
list.add(n);
res.add(list);
return res;
}
else{
for(int i=1;i<=9;i++){
List<List<Integer>> tempRes=combinationSum3(k-1,n-i);
if(tempRes.size()>0){
for(List<Integer> l:tempRes){
l.add(i);
//先检查l中是否有重复的数
Set<Integer> set = new HashSet<Integer>();
set.addAll(l);
if(l.size()!=set.size()){
continue;
}
//对l进行排序
Collections.sort(l);
//先检查res中是否已经存在此结果
if(!isCombinate(res,l)){
res.add(l);
}
}
}
}
return res;
}
}
/*
* 只要res中存在某个list与l中的元素一模一样,则返回true
* */
private boolean isCombinate(List<List<Integer>> res, List<Integer> l) {
for(List<Integer> list:res){
if(list.size()==l.size()){
int i=0;
for(;i<l.size();i++){
if(list.get(i)!=l.get(i)){
break;
}
}
if(i==l.size()){
return true;
}
}
}
return false;
}
public static void main(String[] args){
int k=3;
int n=7;
CombinationSum3 cs = new CombinationSum3();
List<List<Integer>> res = cs.combinationSum3(k,n);
for(List<Integer> list:res){
for(Integer i:list){
System.out.print(i+" ");
}
System.out.println();
}
}
}
当k较小时,是可以通过的,当k较大时,则不能AC。因此,需要寻找更好的方法。
思路二
思路来自于:https://discuss.leetcode.com/topic/26351/simple-and-clean-java-code-backtracking/3
确实经典,想不到。
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
combine(res,new ArrayList<Integer>(),1,k,n);
return res;
}
private void combine(List<List<Integer>> res, ArrayList<Integer> comb,
int start, int k, int n) {
if(comb.size()==k&&n==0){
List<Integer> list = new ArrayList<Integer>(comb);
res.add(list);
return ;
}
if(comb.size()>k||n<1){
return ;
}
for(int i=start;i<=9;i++){
comb.add(i);
combine(res,comb,i+1,k,n-i);
//移除最后加入的那个元素
comb.remove(comb.size()-1);
}
}