Condivisione della tecnologia

Metodo del backtracking di Likou

2024-07-12

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

Cos'è il backtracking?

Durante la ricerca di un determinato nodo, se scopriamo che il nodo corrente (e i suoi sottonodi) non è la destinazione richiesta, torniamo al nodo originale per continuare la ricerca e ripristinare lo stato modificato del nodo corrente.
Ricorda due piccoli consigli:Il primo consiste nel passare lo stato tramite riferimento (&) e il secondo consiste nel modificare tutte le modifiche dello stato una volta completata la ricorsione.
Esistono generalmente due situazioni per le modifiche di backtracking. Una è modificare l'ultimo output, come la permutazione e la combinazione, l'altra è modificare la destinazione di accesso;
Ricorda, ad esempio, di cercare una stringa in una matrice.

46.Disposizione completa

argomento

Dato un array senza numeri duplicatinums, restituiscilotutte le possibili permutazioni .puoiin qualsiasi ordineRispondi.

Esempio 1:

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

Esempio 2:

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

Esempio 3:

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

suggerimento:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • numstutti i numeri interidiversi l'uno dall'altro​​​​​​​
risposta
Per produrre tutte le combinazioni ordinate dell'array, possiamo utilizzare il metodo backtracking.
Determinare innanzitutto una posizione, quindi scambiarla con ciascuna posizione successiva. Dopo aver cambiato, vai alla posizione successiva. Quindi, una volta completata questa serie di passaggi, è necessario sostituire quelli sostituiti. Questo è il metodo del backtracking.
  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. Combinazione

77. Combinazione

argomento

Dati due numeri interinEk, intervallo di ritorno[1, n]tutto possibile dentrokcombinazione di numeri.

puoi premerequalsiasi ordineRispondi.

Esempio 1:

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

Esempio 2:

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

suggerimento:

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

题解

Imposta un conteggio e calcola il numero di ciascuno. Quando count==k, inseriscilo nell'array. Questo è diverso dai precedenti, che erano permutazioni e combinazioni. È un po' come selezionare un array.

A partire da 1-n, imposta un array aggiuntivo per memorizzare i risultati di ogni volta. Il conteggio cambia dinamicamente Dopo aver assegnato i, il conteggio aumenta di uno e viene selezionato un numero da (i+1, n) in dfs. Conta... dopo aver effettuato il backtracing.

  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. Ricerca unità

79. Ricerca di parole

argomento

dato unm x nGriglia di caratteri 2Dboarde una parola stringaword .Sewordesiste nella griglia, ritornatrue; Altrimenti, ritornafalse 。

Le parole devono essere formate da lettere in celle adiacenti in ordine alfabetico, dove le celle "adiacenti" sono quelle adiacenti orizzontalmente o verticalmente. Le lettere nella stessa cella non possono essere utilizzate ripetutamente.

Esempio 1:

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

Esempio 2:

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

Esempio 3:

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

suggerimento:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • boardEwordComposto solo da lettere inglesi maiuscole e minuscole

risposta

Routine simile.

Il metodo dfs + backtracking definisce innanzitutto una visita per contrassegnare se la posizione è stata contrassegnata durante ogni ricerca per evitare che la stessa posizione venga visitata più volte.

Per una posizione, è necessario effettuare una valutazione del confine per determinare se attraversa il confine. Quindi determinare se è stato visitato, se è stato trovato con successo e se la lettera nella posizione è diversa dalla lettera di destinazione.

dfs, cerca in giro.

  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 Regina

51. Regina N

argomento

Secondo le regole degli scacchi, una regina può attaccare un pezzo sulla stessa riga o colonna o sulla stessa diagonale.

n Problema della reginaCiò che si studia è comencollocata la reginan×nsulla scacchiera e rendono le regine incapaci di attaccarsi a vicenda.

Dammi un numero interon, restituisce tutto diversoN problema della reginaLa sua soluzione.

Ogni soluzione ne contiene una diversan Problema della reginaIl piano di posizionamento dei pezzi degli scacchi, in questo piano'Q'E'.'Rappresentano rispettivamente la regina e il posto vuoto.

Esempio 1:

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

Esempio 2:

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

suggerimento:

  • 1 <= n <= 9

题意

N Queen richiede tre funzioni di etichettatura, una è la colonna, una è la diagonale principale e l'altra è la diagonale secondaria.

Poiché ci sarà sicuramente una regina posizionata in ogni riga, viene attraversata riga per riga. Quando l'ultima riga viene attraversata con successo e la regina viene posizionata con successo, è sufficiente. Quindi non è necessario impostare la funzione di marcatura delle righe.

A questo punto possiamo iniziare dalla prima riga e procedere per colonne. Determina se la colonna è falsa, se la diagonale principale è falsa e se la diagonale secondaria è falsa. In tal caso, vai alla colonna successiva. In caso contrario, imposta la posizione su Q, quindi esegui la stessa ricerca per la riga successiva. Metodo di backtracking, ricordarsi di ripristinare la posizione e le funzioni di marcatura dopo la ricerca.

Questo diagonale e subdiagonale. Può essere disegnato sulle coordinate, una è y=x+b, l'altra è y=-x+b.

Quindi b=yx, per rendere b&gt;0, quindi aggiungiamo n. L'altro è 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. };

Riassumere

Per il metodo del backtracking, trovare prima le condizioni al contorno e le condizioni finali. Generalmente, l'i impostato è uguale al numero di righe.

La condizione al contorno è generalmente quella di non oltrepassare il confine.

Generalmente è necessario impostare una funzione di marcatura. Quindi accedi riga per riga o posizione per posizione e la funzione del tag visitato sarà impostata su true. Quindi continua alla riga successiva o successiva (di solito in modo ricorsivo). Quindi ripristinare la funzione di marcatura di cui sopra e tabellone dopo aver terminato (di solito ne verrà impostato uno come risposta). Se corrisponde, push_back nell'array ans.