Technologieaustausch

Likou-Backtracking-Methode

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Was ist Backtracking?

Wenn wir bei der Suche nach einem bestimmten Knoten feststellen, dass der aktuelle Knoten (und seine Unterknoten) nicht das erforderliche Ziel sind, greifen wir auf den ursprünglichen Knoten zurück, um die Suche fortzusetzen und den geänderten Zustand des aktuellen Knotens wiederherzustellen.
Denken Sie an zwei kleine Tipps:Die erste besteht darin, den Status per Referenz (&) zu übergeben, und die zweite darin, alle Statusänderungen nach Abschluss der Rekursion zu ändern.
Im Allgemeinen gibt es zwei Situationen für das Zurückverfolgen von Änderungen: Eine besteht darin, die letzte Ausgabe zu ändern, z. B. Permutation und Kombination, und die andere darin, das Zugriffsziel zu ändern.
Denken Sie beispielsweise an die Suche nach einer Zeichenfolge in einer Matrix.

46.Komplette Anordnung

Thema

Gegeben sei ein Array ohne doppelte Zahlennums, gib es zurückalle möglichen Permutationen .du kannstIn irgendeiner ReihenfolgeAntwort zurückgeben.

Beispiel 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

Beispiel 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

Beispiel 3:

输入:nums = [1]
输出:[[1]]

Hinweis:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • numsalle ganzen Zahlen invoneinander verschieden​​​​​​​
Antwort
Um alle sortierten Kombinationen des Arrays auszugeben, können wir die Backtracking-Methode verwenden.
Bestimmen Sie zunächst eine Position und tauschen Sie diese dann mit jeder weiteren Position aus. Gehen Sie nach dem Wechsel zum nächsten Ort. Nachdem diese Reihe von Schritten abgeschlossen ist, müssen Sie die ersetzten ersetzen. Das ist die Backtracking-Methode.
  1. class Solution {
  2. public:
  3. vector<vector<int>> permute(vector<int>& nums) {
  4. vector<vector<int>> ans;
  5. back(nums,0,ans);
  6. return ans;
  7. }
  8. void back(vector<int>& nums,int n,vector<vector<int>>& ans){
  9. int i;
  10. if(n==nums.size()-1)
  11. ans.push_back(nums);
  12. for(i=n;i<nums.size();i++){
  13. swap(nums[i],nums[n]);
  14. back(nums,n+1,ans);
  15. swap(nums[i],nums[n]);
  16. }
  17. }
  18. };

77. Kombination

77. Kombination

Thema

Gegeben sind zwei ganze ZahlennUndk, Rückgabebereich[1, n]alles möglich inkZahlenkombination.

Sie können drückenjede BestellungAntwort zurückgeben.

Beispiel 1:

输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

Beispiel 2:

输入:n = 1, k = 1
输出:[[1]]

Hinweis:

  • 1 <= n <= 20
  • 1 <= k <= n

题解

Legen Sie eine Anzahl fest und berechnen Sie deren Anzahl. Wenn count==k, fügen Sie sie in das Array ein. Dies unterscheidet sich von den vorherigen, bei denen es sich um Permutationen und Kombinationen handelte. Dies ähnelt in etwa der Auswahl eines Arrays.

Richten Sie ausgehend von 1-n ein zusätzliches Array ein, um die Ergebnisse jeder Zeit zu speichern. Die Anzahl ändert sich dynamisch. Nach der Zuweisung von i erhöht sich die Anzahl um eins und eine Zahl wird aus (i+1, n) in dfs ausgewählt. Zählen – nach der Rückverfolgung.

  1. class Solution {
  2. public:
  3. vector<vector<int>> combine(int n, int k) {
  4. vector<vector<int>> ans;
  5. vector<int> c(k,0);
  6. int count;
  7. dfs(n,k,1,ans,c,count);
  8. return ans;
  9. }
  10. void dfs(int n,int k,int level,vector<vector<int>>& ans,vector<int>& c,int& count){
  11. int i;
  12. if(count==k){
  13. ans.push_back(c);
  14. return ;
  15. }
  16. for(i=level;i<=n;i++){
  17. c[count++]=i;
  18. dfs(n,k,i+1,ans,c,count);
  19. --count;
  20. }
  21. }
  22. };

79. Einheitensuche

79. Wortsuche

Thema

angenommenm x n2D-Zeichenrasterboardund ein Zeichenfolgenwortword .Wennwordexistiert im Raster, kehrt zurücktrue; Ansonsten zurückfalse 。

Wörter müssen aus Buchstaben in benachbarten Zellen in alphabetischer Reihenfolge gebildet werden, wobei „benachbarte“ Zellen diejenigen sind, die horizontal oder vertikal benachbart sind. Buchstaben in derselben Zelle dürfen nicht wiederholt verwendet werden.

Beispiel 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

Beispiel 2:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true

Beispiel 3:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false

Hinweis:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • boardUndwordBesteht nur aus englischen Groß- und Kleinbuchstaben

Antwort

Ähnliche Routine.

Die DFS + Backtracking-Methode definiert zunächst einen Besuch, um zu markieren, ob der Standort bei jeder Suche markiert wurde, um zu verhindern, dass derselbe Standort mehrmals besucht wird.

Für einen Standort muss eine Grenzbeurteilung vorgenommen werden, um festzustellen, ob er die Grenze überschreitet. Stellen Sie dann fest, ob es besucht wurde, ob es erfolgreich gefunden wurde und ob sich der Buchstabe an der Position vom Zielbuchstaben unterscheidet.

dfs, suche herum.

  1. class Solution {
  2. public:
  3. bool exist(vector<vector<char>>& board, string word) {
  4. if(board.empty())
  5. return false;
  6. int m=board.size(),n=board[0].size();
  7. vector<vector<bool>> visit(m,vector<bool>(n,false));
  8. int i,j;
  9. bool find=false;
  10. for(i=0;i<m;i++){
  11. for(j=0;j<n;j++)
  12. back(i,j,board,word,find,visit,0);
  13. }
  14. return find;
  15. }
  16. void back(int i,int j,vector<vector<char>>& board,string& word,
  17. bool& find,vector<vector<bool>>& visit,int level){
  18. if(i<0||i>=board.size()||j<0||j>=board[0].size())
  19. return ;
  20. if(visit[i][j]||find||board[i][j]!=word[level])
  21. return ;
  22. if(level==word.size()-1){
  23. find=true;
  24. return ;
  25. }
  26. visit[i][j]=true;
  27. back(i+1,j,board,word,find,visit,level+1);
  28. back(i-1,j,board,word,find,visit,level+1);
  29. back(i,j+1,board,word,find,visit,level+1);
  30. back(i,j-1,board,word,find,visit,level+1);
  31. visit[i][j]=false;
  32. }
  33. };

51.N Königin

51. Königin N

Thema

Nach den Schachregeln kann eine Dame eine Figur in derselben Reihe oder Spalte oder auf derselben Diagonale angreifen.

n Queen-ProblemEs wird untersucht, wie es gehtnKönigin eingesetztn×nauf dem Schachbrett und verhindern, dass die Damen sich gegenseitig angreifen können.

Geben Sie eine ganze Zahl ann, gibt alles anders zurückN Königinproblems Lösung.

Jede Lösung enthält eine anderen Queen-ProblemDer Plan zur Platzierung der Schachfiguren in diesem Plan'Q'Und'.'Sie repräsentieren jeweils die Königin und den freien Platz.

Beispiel 1:

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

Beispiel 2:

输入:n = 1
输出:[["Q"]]

Hinweis:

  • 1 <= n <= 9

题意

N Queen erfordert drei Beschriftungsfunktionen: eine ist die Spalte, eine ist die Hauptdiagonale und die andere ist die Nebendiagonale.

Da in jeder Reihe auf jeden Fall eine Königin platziert wird, wird diese Reihe für Reihe durchquert. Wenn die letzte Reihe erfolgreich durchquert und die Königin erfolgreich platziert wurde, reicht es aus. Daher ist es nicht erforderlich, die Zeilenmarkierungsfunktion einzustellen.

Zu diesem Zeitpunkt können wir mit der ersten Zeile beginnen und spaltenweise durchlaufen. Bestimmen Sie, ob die Spalte falsch ist, ob die Hauptdiagonale falsch ist und ob die Nebendiagonale falsch ist. Wenn ja, gehen Sie zur nächsten Spalte. Wenn nicht, setzen Sie die Position auf Q und führen Sie dann die gleiche Suche für die nächste Zeile durch. Denken Sie bei der Backtracking-Methode daran, die Positions- und Markierungsfunktionen nach der Suche wiederherzustellen.

Diese Diagonale und Subdiagonale. Es kann anhand der Koordinaten gezeichnet werden, eines ist y=x+b, das andere ist y=-x+b.

Also b=yx, um b&gt;0 zu machen, also addieren wir n. Das andere ist y+x.

  1. class Solution {
  2. public:
  3. vector<vector<string>> solveNQueens(int n) {
  4. vector<vector<string>> ans;
  5. if(n==0)
  6. return {};
  7. vector<string> board(n,string(n,'.'));
  8. vector<bool> c(n,false),l(2*n-1,false),r(2*n-1,false);
  9. back(n,ans,board,c,l,r,0);
  10. return ans;
  11. }
  12. void back(int n,vector<vector<string>>& ans,vector<string>& board,vector<bool>& c,
  13. vector<bool>& l,vector<bool>& r,int row){
  14. if(row==n){
  15. ans.push_back(board);
  16. return ;
  17. }
  18. int i;
  19. for(i=0;i<n;i++){
  20. if(c[i]||l[row-i+n]||r[row+i]){
  21. continue;
  22. }
  23. board[row][i]='Q';
  24. c[i]=l[row-i+n]=r[row+i]=true;
  25. back(n,ans,board,c,l,r,row+1);
  26. board[row][i]='.';
  27. c[i]=l[row-i+n]=r[row+i]=false;
  28. }
  29. }
  30. };

Zusammenfassen

Für die Backtracking-Methode müssen zunächst die Randbedingungen und die Endbedingungen ermittelt werden. Im Allgemeinen ist der i-Satz gleich der Anzahl der Zeilen.

Die Randbedingung besteht im Allgemeinen darin, die Grenze nicht zu überschreiten.

Im Allgemeinen muss eine Markierungsfunktion eingestellt werden. Greifen Sie dann Zeile für Zeile oder Position für Position zu, und die besuchte Tag-Funktion wird auf „true“ gesetzt. Fahren Sie dann mit der nächsten oder nächsten Zeile fort (normalerweise rekursiv). Stellen Sie dann nach Abschluss die obige Markierungsfunktion wieder her und ordnen Sie sie an (normalerweise wird eine als Antwort festgelegt). Wenn es übereinstimmt, push_back zum ans-Array.