力扣hot100——回溯

发布于:2025-02-10 ⋅ 阅读:(28) ⋅ 点赞:(0)

46. 全排列

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> ans;
        vector<int> v;
        vector<int> vis(n, 0);
        auto dfs = [&](this auto&& dfs, int dep) -> void {
            if (dep == n) {
                ans.push_back(v);
                return;
            }
            for (int i = 0; i < n; i++) {
                if (vis[i]) continue;
                vis[i] = 1;
                v.push_back(nums[i]);
                dfs(dep + 1);
                vis[i] = 0;
                v.pop_back();
            }
            };
        dfs(0);
        return ans;
    }
};

78. 子集

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& a) {
        int n = a.size();
        vector<vector<int>> ans;
        for (int i = 0; i < 1 << n; i++) {
            vector<int> v;
            for (int j = 0; j < n; j++) {
                if (i >> j & 1) {
                    v.push_back(a[j]);
                }
            }
            ans.push_back(v);
        }
        return ans;
    }
};

二进制枚举,1表示选,0表示不选

 17. 电话号码的字母组合

class Solution {
public:
    vector<string> letterCombinations(string str) {
        if (str == "") return {};
        vector<string> ans;
        map<char, string> mp;
        int n = str.size();
        mp['2'] = "abc";
        mp['3'] = "def";
        mp['4'] = "ghi";
        mp['5'] = "jkl";
        mp['6'] = "mno";
        mp['7'] = "pqrs";
        mp['8'] = "tuv";
        mp['9'] = "wxyz";
        auto dfs = [&](this auto&& dfs, int dep, string s) -> void {
            if (dep == n) {
                ans.push_back(s);
                return;
            }
            for (auto ch : mp[str[dep]]) {
                dfs(dep + 1, s + ch);
            }
            };
        dfs(0, "");
        return ans;
    }
};

39. 组合总和

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& a, int x) {
        int n = a.size();
        vector<vector<vector<int>>> g(41);
        g[0].push_back({});
        for (int i = 0; i < n; i++) {
            for (int j = a[i]; j <= x; j++) {
                for (auto v : g[j - a[i]]) {
                    v.push_back(a[i]);
                    g[j].push_back(v);
                }
            }
        }
        return g[x];
    }
};

背包记录方案数

 22. 括号生成

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        auto check = [](string s) -> bool {
            if (s.size() & 1) return false;
            int cnt = 0;
            for (int i = 0; i < s.size(); i++) {
                if (s[i] == '(') cnt++;
                else {
                    if (cnt <= 0) return false;
                    cnt--;
                }
            }
            return cnt == 0;
            };
        vector<string> ans;
        auto dfs = [&](this auto&& dfs, int dep, string s) -> void {
            if (dep == 2 * n) {
                if (check(s)) ans.push_back(s);
                return;
            }
            dfs(dep + 1, s + '(');
            dfs(dep + 1, s + ')');
            };
        dfs(0, "");
        return ans;
    }
};

dfs暴搜

 79. 单词搜索

class Solution {
public:
    bool exist(vector<vector<char>>& a, string word) {
        vector<int> dx = { 0, 1, 0, -1 };
        vector<int> dy = { 1, 0, -1, 0 };
        int n = a.size(), m = a[0].size();

        set<char> s;
        for (auto ch : word) s.insert(ch);

        vector<vector<int>> vis(n, vector<int>(m, 0));
        auto dfs = [&](this auto&& dfs, int x, int y, string str) -> bool {
            if (str.size() == word.size()) {
                for (int i = 0; i < str.size(); i++) {
                    if (str[i] != word[i]) return false;
                }
                return true;
            }

            for (int i = 0; i < 4; i++) {
                int tx = x + dx[i], ty = y + dy[i];
                if (tx < 0 || ty < 0 || tx >= n || ty >= m) continue;
                if (vis[tx][ty]) continue;
                if (!s.count(a[tx][ty])) continue;

                string tmp = str;
                tmp += a[tx][ty];
                vis[tx][ty] = 1;
                if (dfs(tx, ty, tmp)) return true;
                vis[tx][ty] = 0;
            }
            return false;
            };

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (s.count(a[i][j]) == 0) continue;
                if (a[i][j] != word[0]) continue;
                string tmp = "";
                tmp += a[i][j];

                vis[i][j] = 1;
                if (dfs(i, j, tmp)) return true;
                vis[i][j] = 0;
            }
        }

        return false;
    }
};

注意dfs里面是 if (dfs(tx, ty, tmp)) return true;

不能直接 return dfs(tx, ty, tmp)

此外字符串拼接用+=

 131. 分割回文串

class Solution {
public:
    vector<vector<string>> partition(string s) {
        int n = s.size();
        vector<vector<string>> ans;
        auto check = [](string s) -> bool {
            for (int i = 0, j = s.size() - 1; i < j; i++, j--) {
                if (s[i] != s[j]) return false;
            }
            return true;
            };
        
        for (int i = 0; i < 1 << n; i++) {
            vector<string> v;
            string str = "";
            int ok = 1;
            for (int j = 0; j < n; j++) {
                str += s[j];
                if (i >> j & 1) {
                    if (check(str)) v.push_back(str);
                    else ok = 0;
                    str = "";
                }
            }
            if (str != "" && check(str)) v.push_back(str);
            else ok = 0;
            if (ok) ans.push_back(v);
        }
        return ans;
    }
};

二进制枚举状态,1表示分割,0表示不分割

51. N 皇后

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> ans;
        if (n == 1) {
            vector<string> v;
            v.push_back("Q");
            ans.push_back(v);
            return ans;
        }
        vector<string> a;
        string s = "";
        for (int i = 0; i < n; i++) {
            s += '.';
        }
        for (int i = 0; i < n; i++) {
            a.push_back(s);
        }

        auto check = [&]() -> bool {
            /*
                check 斜线
            */
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j += n - 1)
                {
                    for (int k = -1; k <= 1; k += 2) {
                        int cnt = 0;
                        int x = i, y = j;
                        while (x >= 0 && y >= 0 && x < n && y < n) {
                            cnt += a[x][y] == 'Q';
                            x++;
                            y += k;
                        }
                        if (cnt > 1) return false;
                    }
                }
            }

            for (int i = 0; i < n; i += n - 1) {
                for (int j = 0; j < n; j++)
                {
                    for (int k = -1; k <= 1; k += 2) {
                        int cnt = 0;
                        int x = i, y = j;
                        while (x >= 0 && y >= 0 && x < n && y < n) {
                            cnt += a[x][y] == 'Q';
                            x++;
                            y += k;
                        }
                        if (cnt > 1) return false;
                    }
                }
            }

            return true;
            };

        auto dfs = [&](this auto&& dfs, int dep, int cnt, int status) -> void {
            if (cnt > n) return;
            if (dep == n) {
                if (cnt == n && check()) ans.push_back(a);
                return;
            }
            for (int i = 0; i < a[dep].size(); i++) {
                if (status >> i & 1) continue;
                a[dep][i] = 'Q';
                dfs(dep + 1, cnt + 1, status | (1 << i));
                a[dep][i] = '.';
            }
            };
        dfs(0, 0, 0);
        return ans;
    }
};

dfs,二进制记录历史列的状态