データ構造バックトラッキング検索アルゴリズム

1.バックトラッキング検索方法で解決できる問題

      (1)組み合わせの問題:たとえば、1、2、3、4、12、13、14、23、24、34に長さ2の組み合わせがいくつかあります。注文は必要ありません

      (2)切断の問題:文字列の切断について話し合った後、切断された部分文字列がすべて回文部分文字列であることを確認します。

      (3)サブセット問題:たとえば、1、2、3、4のすべてのサブセット。注文は必要ありません

      (4)配置の問題:たとえば、1、2、3、4の長さ2のいくつかの組み合わせは、12、13、14、23、24、34、31、21、41、32、42、43です。注文が必要です。

      (4)チェッカーボードの問題:nクイーンの問題

上記の問題をループで解決することは難しいため、上記の問題はバックトラッキング方式で解決する必要があります。

2.バックトラック検索方法のアイデア

バックトラッキングはツリー構造として抽象化でき、バックトラッキングはツリーの水平方向の幅と垂直方向の深さの再帰のforループとして理解できます。

 3.コードを書く一般的なルーチン(テンプレート)

public void backtracking()//バックトラッキング関数を定義する

{{

       // 1、終了条件

         if(終了条件)

         {{

                結果を収集します。

                戻る;

         }
 

      // 2、forループ実行処理ノード、再帰関数、バックトラッキング関数

         for(コレクション要素のトラバース)

        {{

                処理ノード

               再帰関数

               バックトラッキング機能

        }

        最終的なトラバーサル結果を返します。
 

}

4.バックトラッキングアルゴリズムの適用-組み合わせ問題

最初に質問し、長さ2のすべてのセットを1、2、3、および4で取り出します

コードは次のように表示されます。

for(int i = 0; i <num.length; i ++)

{{

             for(int j = i; j <num.length; j ++)

              {{

                    System.out.print(i);

                    System.out.print(j);
              }
}

しかし、上記の配列を100個の数値と50個の長さの組み合わせに変更すると、ネストには50レベルのforループが必要になります。これは明らかに非現実的です。

この時点で、バックトラッキングアルゴリズムを実行する必要があります

この図を説明してください。なぜ、値を取るたびに、次のブランチにこの番号がないのですか。組み合わせの定義では、組み合わせは順序がないため、フロント配列の損失について話さない場合は、必然的にデータの繰り返しが発生します。

コード

再帰関数パラメーターの戻り値

終了条件を決定する

単一レベルの再帰関数

ソースコード:

List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> path= new ArrayList<Integer>();
List<Integer> path2;
public List<List<Integer>> combine(int n, int k)
{
    backstracking(n,k,1);
    return result;

}
public void  backstracking(int n,int k,int startindex)
{
    if(path.size()==k)
    {
        path2=new ArrayList<Integer>();
        for (int i: path)
        {
            path2.add(i);

        }

        result.add(path2);
        return ;
    }
    for(int i=startindex;i<=n;i++)
    {
        path.add(i);
        backstracking(n,k,i+1);//这里为什么是i+1呢因为不能出现两个字母的重复,如果是i的话就会出现11,22,33这种情况。
        path.remove(path.size()-1);

    }
}

5.バックトラッキングアルゴリズムの適用-組み合わせ問題の剪定問題

次の図に示すように、n = 4およびk = 4の場合、純粋に暴力的な検索はコンピューターリソースの大きな浪費になるため、このアルゴリズムを最適化して、このアルゴリズムの時間計算量を低くする必要があります。

 変更する主な点は、サイズがn-(k-path.size)+1に変更されることです。

6.バックトラッキングアルゴリズムの適用-合計

シーン:

繰り返される要素のない配列候補とターゲット数のターゲットが与えられた場合、数の合計をターゲットにすることができる候補のすべての組み合わせを見つけます。

候補者の数は、制限なく繰り返し選択できます。

説明:

すべての数値(ターゲットを含む)は正の整数です。
ソリューションセットに繰り返しの組み合わせを含めることはできません。

アイデア:

コード作成のアイデア

再帰関数パラメーターの戻り値

終了条件を決定する

単一レベルの再帰関数

ソースコード:

import java.util.*;
class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) 
    {
        int sum=0;
        int startindex=0;
        backtracking(candidates,target,sum,startindex);
        return result;

    }
    List<List<Integer>> result=new ArrayList<List<Integer>>();
    List<Integer> path =new ArrayList<Integer>();
    List<Integer> path2;
    public void backtracking(int[] candidates, int target,int sum,int startindex)
    {
        //首先确定函数的参数以及返回值
        if(sum>target)
        {
            return ;
        }
        //确定终止条件
        if(sum==target)
        {
            path2=new ArrayList<Integer>(); 
            for(int i: path)
            {
                path2.add(i);
            }
            result.add(path2);
            return;

        }
        //确定单层递归函数
        for(int i=startindex;i<candidates.length;i++)
        {
            path.add(candidates[i]);
            sum=sum+candidates[i];
            backtracking(candidates,target,sum,i);
            sum=sum-candidates[i];
            path.remove(path.size()-1);

        }
        return ;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

おすすめ

転載: blog.csdn.net/qq_35677589/article/details/112786004