主要思路为:
利用递归,进行深度优先搜索。构造递归函数f(int st,int st2,int lef,List<Integer> ar),st表示本轮搜索ar中开始元素的下标,st2表示最后一个纳入ar的元素下标。例如f(0,0,20,ar)的含义为:从第0个到第0个范围内的元素进行组合,还剩余的目标为20,已经判断合法的中间结果存在ar中。
public static int[] orcan;
public static List<List<Integer>> result;
public static int N = 0;
public static HashSet<List<Integer>> hs;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
N = candidates.length;
Arrays.sort(candidates);
orcan = candidates;
result = new ArrayList<List<Integer>>();
hs = new HashSet();
ArrayList a = new ArrayList();
f(0,0,target,a);
return result;
}
public void f(int st,int st2,int lef,List<Integer> ar){
if(lef==0){
//System.out.println("paixuqian"+ar.toString());
//Collections.sort(ar,new bijiaoqi());
if(hs.contains(ar))
return;
//System.out.println("paixuhou"+ar.toString());
else{
result.add(ar);
hs.add(ar);
return;
}
}
if(st>=N)
return;
if(lef<orcan[0])
return;
if(st2<st)
st2 = st;
for(int i=st;i<N;i++){
if(lef<orcan[i]){
break;
}
for(int j=st2;j<N;j++){
if(lef>=orcan[j]){
ArrayList<Integer> nar = new ArrayList<>(ar);
nar.add(orcan[j]);
st2=j;
f(i,st2+1,lef-orcan[j],nar);
}else{
break;
}
}
}
}
这里有一个优化,即将递归处的f(i,....)变为i+1,可以减少循环的次数,而不影响结果的正确性。这是因为,此时i处的值已经不再会被扫到了。