Leetcode Hot 100 ——回溯part02

22. 括号生成


回溯三部曲

1、递归函数参数

cpp 复制代码
vector<string> result;
 string s;
void backtrack(int left, int right, int n)

left:当前已使用的左括号数量。

right:当前已使用的右括号数量。

n:括号的对数,也是左括号或右括号的最大数量。

2、回溯终止条件

cpp 复制代码
if (left == n && right == n) {
        res.push_back(s);
        return;
    }

3、单层搜索逻辑

在每一层递归中,有两个分支可以选择:添加一个左括号 '(' 或者添加一个右括号 ')'。但必须满足合法性条件(即数量约束)。

cpp 复制代码
if(left<n){
    s.push_back('(');
    backtracking(left+1,right,n);
    s.pop_back();
}
if(right<left){
    s.push_back(')');
    backtracking(left,right+1,n);
    s.pop_back();
}

【注】

1、注意是right<left,不是right<n,因为任何时候,已放置的右括号数量必须小于等于左括号数量(且要保证先有左括号,最终两者相等)。

核心代码:

cpp 复制代码
class Solution {
public:
    vector<string> result;
    string s;
    void backtracking(int left, int right, int n){
        if(left==n&&right==n){
            result.push_back(s);
            return;
        }
        if(left<n){
            s.push_back('(');
            backtracking(left+1,right,n);
            s.pop_back();
        }
        if(right<left){
            s.push_back(')');
            backtracking(left,right+1,n);
            s.pop_back();
        }
    }
    vector<string> generateParenthesis(int n) {
        result.clear();
        s.clear();
        backtracking(0,0,n);
        return result;
        
    }
};

79. 单词搜索(这道题有些不同)


回溯三部曲

1、递归函数参数

cpp 复制代码
bool backtracking(vector<vector<char>>& board,string word,int i,int j,int index)

board:二维字符网格,需要被修改以标记已访问的格子(通过临时替换为特殊字符 '#')

word:目标单词

i, j:当前搜索位置的坐标。

index:当前待匹配的字符在 word 中的下标(从0开始)。当 index == word.size() 时表示所有字符都已匹配完成。

让回溯函数返回 bool 值,这样一旦找到就可以快速终止递归!!

2、回溯终止条件

cpp 复制代码
if (index == word.size()) return true;
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || board[i][j] != word[index])
    return false;

成功终止:当 index 等于单词长度时,说明之前已经匹配完所有字符
失败终止 :如果当前坐标越界,或者当前格子字符与待匹配字符 word[index] 不相等,则此路不通,返回 false。这既是边界检查,也是剪枝条件

3、单层搜索逻辑

cpp 复制代码
char temp = board[i][j];
board[i][j] = '#';  // 标记已访问

bool found = dfs(board, word, i + 1, j, index + 1)
          || dfs(board, word, i - 1, j, index + 1)
          || dfs(board, word, i, j + 1, index + 1)
          || dfs(board, word, i, j - 1, index + 1);

board[i][j] = temp; // 回溯,恢复原字符
return found;

为什么board[i][j] = '#';

在单词搜索的 DFS 过程中,我们需要确保同一个格子不能在一次搜索路径中被重复使用。例如,如果从某个格子出发向四周探索,可能会再次回到这个格子(比如先向右走,下一步再向左回来),这样会导致路径中出现循环,或者错误地认为可以用同一个格子多次匹配单词的不同字符,而实际上每个格子只能用一次。

为了解决这个问题,在进入递归之前,我们临时将当前格子的字符修改为一个特殊标记(如 '#'),表示该格子已被当前路径占用。这样,在后续的递归中,如果试图访问这个格子,会因为字符不匹配(board[i][j] != word[index])而返回 false,从而避免了重复使用。

核心代码:

cpp 复制代码
class Solution {
private:
    bool backtracking(vector<vector<char>>& board,string word,int i,int j,int index){
        if(index == word.size()) return true;
        if(i<0||i>=board.size()||j<0||j>=board[0].size()||board[i][j]!=word[index]) return false;

        char temp = board[i][j];
        board[i][j] = '#';
        bool found = backtracking(board,word,i+1,j,index+1)
                   ||backtracking(board,word,i-1,j,index+1)
                   ||backtracking(board,word,i,j+1,index+1)
                   ||backtracking(board,word,i,j-1,index+1);
        board[i][j] = temp;
        return found;       
    }

public:
    bool exist(vector<vector<char>>& board, string word) {
        for(int i=0;i<board.size();i++){
            for(int j=0;j<board[0].size();j++){
                if(backtracking(board,word,i,j,0)){
                    return true;
                }
            }
        }
        return false;
    }
};

【注】

1、j>=board[0].size()

注意是>=就越界了!!!

2、跟前面的题目不同,不是在exist里直接

cpp 复制代码
return backtracking(board, word, 0, 0, 0);

单词可能在网格的任意位置开始,但这里只从 (0,0) 开始搜索,如果单词起点在其他格子,就会漏掉正确答案。

正确做法是遍历所有格子作为起点,一旦某个起点返回 true,则整个函数返回 true。

51. N皇后

相关推荐
重生之我是Java开发战士10 小时前
【笔试强训】Week1:点击消除,数组中两个字符串的最小距离,dd爱框框,腐烂的苹果,大数乘法
java·开发语言·算法
枫叶林FYL10 小时前
【自然语言处理 NLP】前沿架构与多模态 选择性状态空间模型与并行扫描算法:从原理到实现
算法·自然语言处理·架构
WolfGang00732110 小时前
代码随想录算法训练营 Day29 | 动态规划 part02
算法·动态规划
样例过了就是过了10 小时前
LeetCode热题100 跳跃游戏 II
c++·算法·leetcode·贪心算法·动态规划
rit843249911 小时前
基于NSGA-II的多目标优化算法(MATLAB实现)
开发语言·算法·matlab
香蕉鼠片11 小时前
第三大的数
数据结构·算法·leetcode
汀、人工智能11 小时前
[特殊字符] 第28课:相交链表
数据结构·算法·链表·数据库架构··相交链表
计算机安禾11 小时前
【数据结构与算法】第32篇:交换排序(一):冒泡排序
c语言·数据结构·c++·算法·链表·排序算法·visual studio code
lxh011311 小时前
蜗牛排序题解
javascript·算法
airuike12311 小时前
高性能MEMS IMU:重构无人机飞行控制核心
人工智能·算法·重构·无人机