当前位置: 首页 > news >正文

LeetCodehot 力扣热图100 括号生成

class Solution {
public:
    vector<string> ans; // 存储所有有效括号组合的结果集
    
    vector<string> generateParenthesis(int n) {
        string s; // 当前构建的括号字符串
        backtrack(0, 0, n, s); // 初始调用回溯函数
        return ans;
    }
    
    void backtrack(int open, int close, int n, string &s) {
        // 终止条件:当前字符串长度等于2n,说明得到一个有效组合
        if (s.size() == 2 * n) {
            ans.push_back(s);
            return;
        }
        
        // 添加左括号的条件:已使用左括号数小于n
        if (open < n) {
            s.push_back('('); // 选择:添加左括号
            backtrack(open + 1, close, n, s); // 递归探索后续可能性
            s.pop_back(); // 回溯:撤销选择,尝试其他可能性
        }
        
        // 添加右括号的条件:已使用右括号数小于左括号数
        if (close < open) {
            s.push_back(')'); // 选择:添加右括号
            backtrack(open, close + 1, n, s); // 递归探索后续可能性
            s.pop_back(); // 回溯:撤销选择,尝试其他可能性
        }
    }
};

以下是当 `n=3` 时,回溯算法生成所有有效括号组合的详细运行步骤和回溯过程分析:

---

### **递归步骤详解(n=3)**
#### **初始状态**
- `open=0`, `close=0`, `s=""`

---

#### **步骤1:添加第一个左括号**
```plaintext
s = "("
open=1, close=0
递归调用 backtrack(1,0,3,"(")
```

---

#### **步骤2:添加第二个左括号**
```plaintext
s = "(("
open=2, close=0
递归调用 backtrack(2,0,3,"((")
```

---

#### **步骤3:添加第三个左括号**
```plaintext
s = "((("
open=3, close=0
递归调用 backtrack(3,0,3,"(((")
```

---

#### **步骤4:添加右括号(close < open)**
```plaintext
s = "((()"
open=3, close=1
递归调用 backtrack(3,1,3,"((()")
```

---

#### **步骤5:继续添加右括号**
```plaintext
s = "((())"
open=3, close=2
递归调用 backtrack(3,2,3,"((())")
```

---

#### **步骤6:完成第一个有效组合**
```plaintext
s = "((()))"
open=3, close=3
递归终止,保存结果 "((()))"
回溯到步骤5 → s = "((())"
```

---

#### **步骤7:回溯并探索其他路径**
```plaintext
回溯到步骤4 → s = "((()"
添加右括号:
s = "((())"
open=3, close=2 → 重复步骤5-6,但已处理
继续回溯到步骤3 → s = "((("
无法添加更多左括号(open=3),添加右括号:
s = "((()"
open=3, close=1 → 重复步骤4
```

---

#### **步骤8:回溯到步骤2 → s = "(("**
```plaintext
添加右括号(close < open):
s = "(()"
open=2, close=1
递归调用 backtrack(2,1,3,"(()")
```

---

#### **步骤9:添加左括号**
```plaintext
s = "(()("
open=3, close=1
递归调用 backtrack(3,1,3,"(()(")
添加右括号:
s = "(()()"
open=3, close=2
递归调用 backtrack(3,2,3,"(()()")
继续添加右括号:
s = "(()())"
保存结果 "(()())"
回溯到 s = "(()()" → 弹出右括号
```

---

#### **步骤10:回溯到 s = "(()("**
```plaintext
无法添加左括号(open=3),添加右括号:
s = "(()())" → 已保存
继续回溯到 s = "(()"
```

---

#### **步骤11:回溯到 s = "(()"**
```plaintext
添加右括号(close < open):
s = "(())"
open=2, close=2
递归调用 backtrack(2,2,3,"(())")
```

---

#### **步骤12:添加左括号**
```plaintext
s = "(())("
open=3, close=2
递归调用 backtrack(3,2,3,"(())(")
添加右括号:
s = "(())()"
保存结果 "(())()"
回溯到 s = "(())(" → 弹出左括号
```

---

#### **步骤13:回溯到 s = "(())"**
```plaintext
添加右括号:
s = "(())" → 无法继续(close=2 < open=2 不成立)
回溯到 s = "(()"
```

---

#### **步骤14:回溯到步骤1 → s = "("**
```plaintext
添加右括号(close < open):
s = "()"
open=1, close=1
递归调用 backtrack(1,1,3,"()")
```

---

#### **步骤15:添加左括号**
```plaintext
s = "()("
open=2, close=1
递归调用 backtrack(2,1,3,"()(")
添加左括号:
s = "()(("
open=3, close=1
递归调用 backtrack(3,1,3,"()((")
添加右括号:
s = "()(()"
→ 继续递归直到生成 "()(())"
保存结果 "()(())"
回溯到 s = "()(()" → 弹出右括号
```

---

#### **步骤16:回溯到 s = "()(("**
```plaintext
添加右括号:
s = "()(()" → 重复
继续回溯到 s = "()("
添加右括号:
s = "()()"
open=2, close=2
递归调用 backtrack(2,2,3,"()()")
```

---

#### **步骤17:添加左括号**
```plaintext
s = "()()("
open=3, close=2
递归调用 backtrack(3,2,3,"()()(")
添加右括号:
s = "()()()"
保存结果 "()()()"
```

---

### **最终结果**
所有有效组合(共5种):
1. `((()))`
2. `(()())`
3. `(())()`
4. `()(())`
5. `()()()`

---

### **关键回溯路径图(简化版)**
```plaintext
开始(空字符串)
|
├─ 添加'(' → "("
│   ├─ 添加'(' → "(("
│   │   ├─ 添加'(' → "((("
│   │   │   └─ 添加')' → "((()" → ... → "((()))"
│   │   └─ 添加')' → "(()" → ... → "(()())", "(())()"
│   └─ 添加')' → "()"
│       ├─ 添加'(' → "()(" → ... → "()(())", "()()()"
│       └─ 添加')' → 无效(剪枝)
└─ 添加')' → 无效(剪枝)
```

---

### **算法核心逻辑**
1. **左括号优先**:只要左括号未达 `n`,优先添加左括号。
2. **右括号限制**:右括号数量必须小于左括号时才能添加。
3. **回溯剪枝**:通过 `s.pop_back()` 撤销无效尝试,避免重复路径。

此过程通过递归和回溯系统地探索所有可能的组合,并利用剪枝条件确保每一步都是有效的。

相关文章:

  • 水仙花数(华为OD)
  • 2025-03-01 学习记录--C/C++-PTA 7-35 有理数均值
  • CountDownLatch使用
  • DeepSeek 开源周五个开源项目,引领 AI 创新?
  • 构建神经网络之Matplotlib(持续完善)
  • 生态安全相关
  • 【 开发知识点 一 】 随机数生成器 /dev/urandom 和 /dev/random
  • 《几何原本》命题I.1
  • aws(学习笔记第三十课) 练习使用transit gateway
  • yolov12 部署瑞芯微 rk3588、RKNN 部署工程难度小、模型推理速度快
  • 计算机毕业设计Python+DeepSeek-R1大模型游戏推荐系统 Steam游戏推荐系统 游戏可视化 游戏数据分析(源码+文档+PPT+讲解)
  • 计算机网络之传输层(tcp协议)
  • kubernetes 高可用集群搭建
  • Dify v1.0.0 里程碑版本正式亮相
  • Metal学习笔记九:光照基础
  • WPF高级 | WPF 与数据库交互:连接、查询与数据更新
  • 《操作系统 - 清华大学》 8 -11:进程管理:上下文切换
  • 从零开始用react + tailwindcss + express + mongodb实现一个聊天程序(六) 导航栏 和 个人信息设置
  • C语言基础系列【17】位域
  • 【NLP 30、大模型中的 ”Token“】
  • 做推广用那个网站吗/中国万网官网
  • 网页设计介绍北京网站/又一病毒来了比新冠可怕
  • 做视频网站的上市公司/莆田seo推广公司
  • 宁波网站公司/深圳居家办公
  • 国外美甲网站模板/互联网营销师培训费用是多少
  • 开发公司和物业公司/河源市seo点击排名软件价格