序文
今日の質問はつらい教訓です。考えは正しいですが、サイクル条件は省略されています。手で書くこともできますが…
トピック
ターゲットとして配列内のすべての合計の組み合わせを見つけます
たとえば、配列が[2,2,3,4]でtarget = 7の場合
、すべての組み合わせは
[2,2,3]、[3,4]になります。
アイデア
剪定のバックトラック、すべての状況のトラバース、dfsテンプレートの質問
sumは一時的な合計を保存し、tmpは一時的な組み合わせを保存し、インデックスは現在の深さまで再帰します。sum
== targetの場合、現在のtmpは有効な組み合わせであり、回答セットに追加されます。
sum + arr [index]がすでにターゲットよりも大きい場合は、この時点でarr [index]を追加して、直接返す必要はありません。(この操作は枝刈りを表します)
index == arr.lengthの場合、配列が範囲外になるため、戻る必要があります(これは境界条件チェックを表します)
各配列の位置をループする必要があり、すべてを再帰的に検索する必要があります。検索後、すべての組み合わせが次のノードから確実に見つかるようにバックトラックする必要があります。
一度だけトラバースされた場合、最初の要素が削除された後、2番目の要素からすべての組み合わせを再帰的に検索し続けることはできません。
コード
public class Solution {
//使用Set集合来去重
static Set<List<Integer>> res = new HashSet<List<Integer>>();
static List<Integer> tmp = new LinkedList<Integer>();
public static void main(String[] args) {
int[] arr = {
2,2,3,2,4,1,6,5,2,7,0,1,1,1,1,1,1,1};
int target = 7;
dfs(arr,target,0,0);
printResult(res);
}
public static void dfs(int[] arr,int target,int sum,int index) {
if(sum == target){
res.add(new LinkedList<Integer>(tmp));
return;
}
if(index >= arr.length) return;
if(sum + arr[index] > target) return;
for(int i = index; i<arr.length; i++) {
tmp.add(arr[i]);
dfs(arr,target,sum+arr[i],i+1);
tmp.remove(tmp.size()-1);
}
}
public static void printResult(Set<List<Integer>> res) {
Iterator iterator = res.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
試験結果
総括する
誰もがバックトラックに精通していると思いますが、突然その場で書くときは、コードをコーディングする前に明確な心を持って、先に進む前によく考えておく必要があります。
共有を主張し、独創性を主張し、ブロガーが好きな可愛い女の子はブロガーのホームページブログをチェックすることができます!
あなたの好きなものやお気に入りは、ブログを共有するための私の最大の感謝です!
Bloggerブログアドレス:https://blog.csdn.net/weixin_43967679