Κοινή χρήση τεχνολογίας

Μέθοδος Likou-backtracking

2024-07-12

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

Τι είναι το backtracking;

Κατά την αναζήτηση ενός συγκεκριμένου κόμβου, εάν διαπιστώσουμε ότι ο τρέχων κόμβος (και οι υποκόμβοι του) δεν είναι ο απαιτούμενος στόχος, επιστρέφουμε στον αρχικό κόμβο για να συνεχίσουμε την αναζήτηση και να επαναφέρουμε την τροποποιημένη κατάσταση του τρέχοντος κόμβου.
Θυμηθείτε δύο μικρές συμβουλές:Το πρώτο είναι να περάσει η κατάσταση με αναφορά (&) και το δεύτερο είναι να αλλάξει όλες οι τροποποιήσεις κατάστασης μετά την ολοκλήρωση της αναδρομής.
Υπάρχουν γενικά δύο περιπτώσεις για τις τροποποιήσεις backtracking.
Θυμηθείτε, για παράδειγμα, την αναζήτηση μιας συμβολοσειράς σε έναν πίνακα.

46.Πλήρης διάταξη

θέμα

Δίνεται ένας πίνακας χωρίς διπλούς αριθμούςnums, επιστρέψτε τοόλες τις πιθανές μεταθέσεις .μπορείςμε οποιαδήποτε σειράΕπιστροφή απάντηση.

Παράδειγμα 1:

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

Παράδειγμα 2:

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

Παράδειγμα 3:

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

ίχνος:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • numsόλοι οι ακέραιοι αριθμοί μέσαδιαφορετικοί μεταξύ τους​​​​​​​
απάντηση
Για την έξοδο όλων των ταξινομημένων συνδυασμών του πίνακα, μπορούμε να χρησιμοποιήσουμε τη μέθοδο backtracking.
Καθορίστε πρώτα μια θέση και, στη συνέχεια, ανταλλάξτε την με κάθε επόμενη θέση. Αφού αλλάξετε, μεταβείτε στην επόμενη τοποθεσία. Στη συνέχεια, αφού ολοκληρωθεί αυτή η σειρά βημάτων, πρέπει να αντικαταστήσετε τα αντικατασταθέντα. Αυτή είναι η μέθοδος 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. Συνδυασμός

77. Συνδυασμός

θέμα

Δίνονται δύο ακέραιοι αριθμοίnκαιk, εύρος επιστροφής[1, n]όλα δυνατά σεkσυνδυασμό αριθμών.

μπορείτε να πατήσετεοποιαδήποτε παραγγελίαΕπιστροφή απάντηση.

Παράδειγμα 1:

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

Παράδειγμα 2:

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

ίχνος:

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

题解

Ορίστε έναν αριθμό και υπολογίστε τον αριθμό του καθενός. Αυτό είναι διαφορετικό από τα προηγούμενα, που ήταν μεταθέσεις και συνδυασμοί. Αυτό μοιάζει λίγο με την επιλογή ενός πίνακα.

Ξεκινώντας από το 1-n, ρυθμίστε έναν επιπλέον πίνακα για να αποθηκεύσετε τα αποτελέσματα κάθε φορά. Η μέτρηση αλλάζει δυναμικά Μετά την εκχώρηση i, η μέτρηση αυξάνεται κατά ένα και επιλέγεται ένας αριθμός από (i+1, n) σε dfs. Μέτρηση-- μετά την αναδρομή.

  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. Αναζήτηση μονάδας

79. Αναζήτηση λέξεων

θέμα

δίνεται αm x nΔισδιάστατο πλέγμα χαρακτήρωνboardκαι μια λέξη χορδήword .ανwordυπάρχει στο πλέγμα, επιστρέφειtrueΔιαφορετικά, επιστρέψτεfalse 。

Οι λέξεις πρέπει να σχηματίζονται από γράμματα σε γειτονικά κελιά με αλφαβητική σειρά, όπου "γειτονικά" κελιά είναι εκείνα που είναι γειτονικά οριζόντια ή κάθετα. Τα γράμματα στο ίδιο κελί δεν επιτρέπεται να χρησιμοποιούνται επανειλημμένα.

Παράδειγμα 1:

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

Παράδειγμα 2:

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

Παράδειγμα 3:

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

ίχνος:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • boardκαιwordΑποτελείται μόνο από κεφαλαία και πεζά αγγλικά γράμματα

απάντηση

Παρόμοια ρουτίνα.

Η μέθοδος backtracking dfs + ορίζει πρώτα μια επίσκεψη για να επισημάνει εάν η τοποθεσία έχει επισημανθεί κατά τη διάρκεια κάθε αναζήτησης για να αποτρέψει την επανειλημμένη επίσκεψη της ίδιας τοποθεσίας.

Για μια τοποθεσία, πρέπει να γίνει μια οριακή κρίση για να καθοριστεί εάν διασχίζει το όριο. Στη συνέχεια, καθορίστε εάν έχει επισκεφθεί, εάν βρέθηκε με επιτυχία και εάν το γράμμα στη θέση είναι διαφορετικό από το γράμμα-στόχο.

dfs, ψάξε τριγύρω.

  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.Ν Βασίλισσα

51. Βασίλισσα Ν

θέμα

Σύμφωνα με τους κανόνες του σκακιού, μια βασίλισσα μπορεί να επιτεθεί σε ένα κομμάτι στην ίδια σειρά ή στήλη ή στην ίδια διαγώνιο.

n Πρόβλημα βασίλισσαςΑυτό που μελετάται είναι πώς ναnβασίλισσα τοποθετείται μέσαn×nστη σκακιέρα, και κάνουν τις βασίλισσες να μην μπορούν να επιτεθούν η μία στην άλλη.

Σας δίνουμε έναν ακέραιοn, επιστρέφει όλα διαφορετικάn πρόβλημα βασίλισσαςs λύση.

Κάθε λύση περιέχει διαφορετικήn Πρόβλημα βασίλισσαςΤο σχέδιο τοποθέτησης σκακιού, σε αυτό το σχέδιο'Q'και'.'Αντιπροσωπεύουν τη βασίλισσα και την άδεια έδρα αντίστοιχα.

Παράδειγμα 1:

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

Παράδειγμα 2:

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

ίχνος:

  • 1 <= n <= 9

题意

Το N Queen απαιτεί τρεις συναρτήσεις σήμανσης, μία είναι η στήλη, μία είναι η κύρια διαγώνιος και η άλλη είναι η δευτερεύουσα διαγώνιος.

Επειδή σίγουρα θα τοποθετηθεί μια βασίλισσα σε κάθε σειρά, διασχίζεται σειρά με σειρά Όταν η τελευταία σειρά διανυθεί με επιτυχία και η βασίλισσα τοποθετηθεί με επιτυχία, είναι αρκετό. Επομένως, δεν χρειάζεται να ρυθμίσετε τη λειτουργία σήμανσης σειρών.

Αυτή τη στιγμή μπορούμε να ξεκινήσουμε από την πρώτη σειρά και να διασχίσουμε στήλες. Προσδιορίστε εάν η στήλη είναι ψευδής, εάν η κύρια διαγώνιος είναι ψευδής και εάν η δευτερεύουσα διαγώνιος είναι ψευδής. Εάν ναι, μεταβείτε στην επόμενη στήλη Εάν όχι, ορίστε τη θέση σε Q και, στη συνέχεια, εκτελέστε την ίδια αναζήτηση για την επόμενη σειρά. Μέθοδος backtracking, θυμηθείτε να επαναφέρετε τις λειτουργίες θέσης και σήμανσης μετά την αναζήτηση.

Αυτή η διαγώνιος και υποδιαγώνιος. Μπορεί να σχεδιαστεί στις συντεταγμένες, η μία είναι y=x+b, η άλλη είναι y=-x+b.

Άρα b=yx, για να κάνουμε b&gt;0, οπότε προσθέτουμε n. Το άλλο είναι 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. };

Συνοψίζω

Για τη μέθοδο backtracking, βρείτε πρώτα τις οριακές συνθήκες και τις συνθήκες λήξης. Γενικά, το σύνολο i είναι ίσο με τον αριθμό των σειρών.

Η οριακή συνθήκη είναι γενικά να μην υπερβείτε το όριο.

Γενικά, πρέπει να οριστεί μια λειτουργία σήμανσης. Στη συνέχεια, αποκτήστε πρόσβαση γραμμή προς γραμμή ή θέση προς θέση και η συνάρτηση ετικέτας επίσκεψης ορίζεται σε true. Στη συνέχεια, συνεχίστε στην επόμενη ή επόμενη γραμμή (συνήθως αναδρομικά). Στη συνέχεια, επαναφέρετε την παραπάνω λειτουργία σήμανσης και την πλακέτα μετά την ολοκλήρωση (συνήθως ορίζεται μία ως απάντηση). Εάν ταιριάζει, push_back στον πίνακα ans.