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皇后

相关推荐
for_ever_love__2 小时前
Objective-C学习 类别和扩展
学习·算法·objective-c
ArturiaZ2 小时前
【day53】
开发语言·c++·算法
历程里程碑2 小时前
36 Linux线程池实战:日志与策略模式解析
开发语言·数据结构·数据库·c++·算法·leetcode·哈希算法
可编程芯片开发2 小时前
基于自适应MUSIC算法的波束形成matlab仿真
算法·matlab·波束形成·自适应music
2301_789015622 小时前
DS进阶:红黑树
c语言·开发语言·数据结构·c++·算法·r-tree·lsm-tree
郝学胜-神的一滴2 小时前
深度学习浪潮:解锁技术边界与产业新图景
数据结构·人工智能·python·深度学习·算法
daxi1502 小时前
C语言从入门到进阶——第13讲:深入理解指针(3)
c语言·开发语言·数据结构·算法
white-persist2 小时前
【CTF线下赛 AWD】AWD 比赛全维度实战解析:从加固防御到攻击拿旗
网络·数据结构·windows·python·算法·安全·web安全
liuyao_xianhui2 小时前
动态规划_简单多dp问题_打家劫舍_打家劫舍2_C++
java·开发语言·c++·算法·动态规划