LeetCode Hot 100:回溯

LeetCode Hot 100:回溯

46. 全排列

class Solution {
private:
    vector<vector<int>> ans;

public:
    vector<vector<int>> permute(vector<int>& nums) {
        if (nums.empty())
            return {};

        backtrace(nums, 0, (int)nums.size());
        return ans;
    }
    void backtrace(vector<int>& path, int level, int n) {
        if (level == n) {
            ans.push_back(path);
            return;
        }

        for (int i = level; i < n; i++) {
            swap(path[i], path[level]);
            backtrace(path, level + 1, n);
            swap(path[i], path[level]);
        }
    }
};

78. 子集

class Solution {
private:
    vector<vector<int>> ans;

public:
    vector<vector<int>> subsets(vector<int>& nums) {
        if (nums.empty())
            return {};

        vector<int> path;
        backtrace(nums, 0, (int)nums.size(), path);

        return ans;
    }
    void backtrace(vector<int>& nums, int level, int n, vector<int> path) {
        if (level == n) {
            ans.push_back(path);
            return;
        }

        path.push_back(nums[level]);
        backtrace(nums, level + 1, n, path);
        path.pop_back();
        backtrace(nums, level + 1, n, path);
    }
};

17. 电话号码的字母组合

class Solution {
private:
    unordered_map<char, string> dict{
        {'2', "abc"}, {'3', "def"},  {'4', "ghi"}, {'5', "jkl"},
        {'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"}};

    vector<string> ans;

public:
    vector<string> letterCombinations(string digits) {
        if (digits.empty())
            return {};

        int n = digits.length();
        string path;
        backtrace(digits, 0, n, path);

        return ans;
    }
    void backtrace(string& digits, int level, int n, string path) {
        if (level == n) {
            ans.push_back(path);
            return;
        }

        char digit = digits[level];
        string s = dict[digit];

        for (char& c : s) {
            path.push_back(c);
            backtrace(digits, level + 1, n, path);
            path.pop_back();
        }
    }
};

39. 组合总和

class Solution {
private:
    vector<vector<int>> ans;

public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        if (candidates.empty())
            return {};

        int n = candidates.size();
        vector<int> path;
        backtrace(candidates, 0, n, target, path);

        return ans;
    }
    void backtrace(vector<int>& nums, int level, int n, int target,
                   vector<int> path) {
        if (level == n)
            return;
        if (accumulate(path.begin(), path.end(), 0) == target) {
            ans.push_back(path);
            return;
        }

        // 选 nums[level]
        if (accumulate(path.begin(), path.end(), 0) + nums[level] <= target) {
            path.push_back(nums[level]);
            backtrace(nums, level, n, target, path);
            path.pop_back();
        }
        // 不选 nums[level]
        backtrace(nums, level + 1, n, target, path);
    }
};

22. 括号生成

思路 1:回溯

class Solution {
private:
    vector<string> ans;

public:
    vector<string> generateParenthesis(int n) {
        if (n == 0)
            return {};

        string path;
        backtrace(0, 2 * n, path);

        return ans;
    }
    void backtrace(int level, int n, string path) {
        if (level == n) {
            if (isValid(path))
                ans.push_back(path);
            return;
        }

        path.push_back('(');
        backtrace(level + 1, n, path);
        path.pop_back();

        path.push_back(')');
        backtrace(level + 1, n, path);
        path.pop_back();
    }
    // 辅函数 - 判断字符串 s 是否有效
    bool isValid(const string& s) {
        int balance = 0;
        for (const char& c : s) {
            if (c == '(')
                balance++;
            else
                balance--;
            if (balance < 0)
                return false;
        }
        return balance == 0;
    }
};

思路 2:深度优先搜索

class Solution {
private:
    vector<string> ans;

public:
    vector<string> generateParenthesis(int n) {
        if (n == 0)
            return {};

        function<void(int, int, string)> dfs = [&](int left, int right, string str) {
            if (left < 0 || right < 0 || left > right)
                return;
            if (left == 0 && right == 0) {
                ans.push_back(str);
                return;
            }

            dfs(left - 1, right, str + '(');
            dfs(left, right - 1, str + ')');
        };

        dfs(n, n, "");

        return ans;
    }
};

79. 单词搜索

/*
 * @lc app=leetcode.cn id=79 lang=cpp
 *
 * [79] 单词搜索
 */

// @lc code=start
class Solution {
private:
    const int dx[4] = {0, 0, 1, -1};
    const int dy[4] = {1, -1, 0, 0};

public:
    // 主函数
    bool exist(vector<vector<char>>& board, string word) {
        if (board.empty())
            return false;

        int m = board.size(), n = m ? board[0].size() : 0;
        vector<vector<bool>> visited(m, vector<bool>(n, false));
        bool find = false;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                backtrack(i, j, 0, board, word, find, visited);

        return find;
    }
    // 辅函数(注意传引用,否则TLE)
    void backtrack(int i, int j, int level, vector<vector<char>>& board,
                   string& word, bool& find, vector<vector<bool>>& visited) {
        if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size())
            return;
        if (visited[i][j] || find || board[i][j] != word[level])
            return;
        if (level == word.size() - 1) {
            find = true;
            return;
        }

        visited[i][j] = true; // 修改当前节点状态
        // 递归子节点
        for (int k = 0; k < 4; k++) {
            int r = i + dx[k];
            int c = j + dy[k];
            backtrack(r, c, level + 1, board, word, find, visited);
        }
        visited[i][j] = false; // 回改当前节点状态
    }
};
// @lc code=end

131. 分割回文串

/*
 * @lc app=leetcode.cn id=131 lang=cpp
 *
 * [131] 分割回文串
 */

// @lc code=start

// 回溯

class Solution {
private:
    vector<vector<string>> ans;

public:
    vector<vector<string>> partition(string s) {
        int n = s.length();

        vector<string> path;
        backtrack(s, 0, n, 0, path);

        return ans;
    }
    void backtrack(string s, int level, int n, int start, vector<string> path) {
        if (level == n) {
            ans.push_back(path);
            return;
        }

        if (level < n - 1) {
            // 跳过当前字符 s[level]
            backtrack(s, level + 1, n, start, path);
        }

        if (isPalindrome(s, start, level)) {
            // s[start, level] 是一个回文串
            string tmp = s.substr(start, level - start + 1);
            path.push_back(tmp);
            // 下一个回文串从 level+1 开始
            backtrack(s, level + 1, n, level + 1, path);
            // 回溯
            path.pop_back();
        }
    }
    // 辅函数 - 判断字符串 s 的 [left, right] 部分是否回文
    bool isPalindrome(const string& s, int left, int right) {
        while (left < right) {
            if (s[left] != s[right])
                return false;
            left++;
            right--;
        }
        return true;
    }
};
// @lc code=end

51. N 皇后

class Solution {
private:
    vector<vector<string>> ans;

public:
    vector<vector<string>> solveNQueens(int n) {
        if (n == 0)
            return {};

        // 初始化棋局
        vector<string> board(n, string(n, '.'));
        // 每行每行放置皇后
        backtrack(board, 0, n);

        return ans;
    }
    void backtrack(vector<string> board, int row, int n) {
        if (row == n) {
            ans.push_back(board);
            return;
        }

        for (int col = 0; col < n; col++) {
            if (check(board, row, col, n) == false)
                continue;
            board[row][col] = 'Q';
            backtrack(board, row + 1, n);
            board[row][col] = '.';
        }
    }
    bool check(const vector<string>& board, int row, int col, int n) {
        // 同一列
        for (int i = 0; i < row; i++)
            if (board[i][col] == 'Q')
                return false;

        // 斜上方
        for (int i = row, j = col; i >= 0 && j >= 0; i--, j--)
            if (board[i][j] == 'Q')
                return false;

        for (int i = row, j = col; i >= 0 && j <= n; i--, j++)
            if (board[i][j] == 'Q')
                return false;

        return true;
    }
};
### LeetCode Hot 100 Problems Python Solutions 以下是针对LeetCode热门100题中的部分经典题目提供Python实现方案: #### 两数之和 (Two Sum) 通过暴力解法可以遍历数组两次来找到目标值对应的索引位置[^1]。 ```python class Solution(object): def twoSum(self, nums, target): for i in range(len(nums)): for j in range(i + 1, len(nums)): if nums[i] + nums[j] == target: return [i, j] return [] ``` 另一种更高效的解决方案是利用哈希表减少时间复杂度至O(n)[^4]: ```python class Solution(object): def twoSum(self, nums, target): hash_map = {} for index, value in enumerate(nums): complement = target - value if complement in hash_map: return [hash_map[complement], index] hash_map[value] = index return [] ``` --- #### 组合总和 (Combination Sum) 此问题可以通过回溯算法解决,递归构建满足条件的结果集[^2]。 ```python class Solution: def combinationSum(self, candidates, target): result = [] def backtrack(remain, comb, start): if remain == 0: result.append(list(comb)) return elif remain < 0: return for i in range(start, len(candidates)): comb.append(candidates[i]) backtrack(remain - candidates[i], comb, i) comb.pop() backtrack(target, [], 0) return result ``` --- #### 全排列 (Permutations) 对于全排列问题,同样采用回溯方法生成所有可能的排列组合。 ```python class Solution: def permute(self, nums): res = [] def backtrack(path, options): if not options: res.append(path[:]) return for i in range(len(options)): path.append(options[i]) backtrack(path, options[:i] + options[i+1:]) path.pop() backtrack([], nums) return res ``` --- #### 最长连续序列 (Longest Consecutive Sequence) 该问题的核心在于使用集合数据结构优化查找效率,从而降低整体的时间复杂度[^3]。 ```python class Solution: def longestConsecutive(self, nums): longest_streak = 0 num_set = set(nums) for num in num_set: if num - 1 not in num_set: current_num = num current_streak = 1 while current_num + 1 in num_set: current_num += 1 current_streak += 1 longest_streak = max(longest_streak, current_streak) return longest_streak ``` --- #### 字符串中所有字母异位词 (Find All Anagrams in a String) 滑动窗口配合字符计数器能够高效解决问题。 ```python from collections import defaultdict class Solution: def findAnagrams(self, s, p): need = defaultdict(int) window = defaultdict(int) valid = 0 for c in p: need[c] += 1 left, right = 0, 0 res = [] while right < len(s): c = s[right] right += 1 if c in need: window[c] += 1 if window[c] == need[c]: valid += 1 while right - left >= len(p): if valid == len(need): res.append(left) d = s[left] left += 1 if d in need: if window[d] == need[d]: valid -= 1 window[d] -= 1 return res ``` --- #### 两数相加 (Add Two Numbers) 链表操作的经典案例之一,需注意进位处理逻辑。 ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next class Solution: def addTwoNumbers(self, l1, l2): dummy_head = ListNode(0) curr = dummy_head carry = 0 while l1 or l2 or carry: x = l1.val if l1 else 0 y = l2.val if l2 else 0 total = x + y + carry carry = total // 10 curr.next = ListNode(total % 10) curr = curr.next if l1: l1 = l1.next if l2: l2 = l2.next return dummy_head.next ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值