news 2026/5/24 6:06:24

力扣 22. 括号生成:C++ 实现回溯 + 动态规划双解法,面试高频题必掌握

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
力扣 22. 括号生成:C++ 实现回溯 + 动态规划双解法,面试高频题必掌握

在算法面试中,括号生成问题是经典的字符串组合题型,力扣第 22 题「括号生成」更是高频考点。题目要求给定括号对数 n,生成所有有效的括号组合,看似简单却能深度考察对回溯、动态规划等核心算法思想的掌握。今天用 C++ 实现两种最优解法,兼顾代码简洁性和可读性,小白也能轻松理解!

一、题目核心分析

  • 输入:括号对数 n(1≤n≤8)
  • 输出:所有有效括号组合(有效 = 左右括号数量相等 + 每一步左括号数≥右括号数)
  • 示例:n=3 时,输出 ["((()))","(()())","(())()","()(())","()()()"]

关键约束:生成过程中必须保证「左括号未用完时可加左括号,右括号数量小于左括号时可加右括号」,这是避免无效组合的核心。

二、解法一:回溯算法(最优解)

回溯本质是「试探 - 回退」的深度优先搜索,通过剪枝避免无效路径,效率极高,也是 C++ 面试中最推荐的写法。

核心思路

  1. 定义辅助递归函数,参数包含当前组合字符串、左括号使用数、右括号使用数和结果集(引用传递)。
  2. 终止条件:左右括号均用完(字符串长度 = 2n),将当前组合加入结果集。
  3. 剪枝逻辑:
    • 左括号未用完(left < n):可添加左括号,递归继续。
    • 右括号少于左括号(right < left):可添加右括号,递归继续。

代码实现(C++)

#include <vector> #include <string> using namespace std; class Solution { public: vector<string> generateParenthesis(int n) { vector<string> result; backtrack("", 0, 0, n, result); return result; } private: // 回溯函数:当前字符串、左括号数、右括号数、总对数、结果集 void backtrack(string current, int left, int right, int n, vector<string>& result) { // 终止条件:字符串长度达到2n(左右括号均用完) if (current.size() == 2 * n) { result.push_back(current); return; } // 左括号未用完,可添加左括号 if (left < n) { backtrack(current + '(', left + 1, right, n, result); } // 右括号数量小于左括号,可添加右括号(保证有效) if (right < left) { backtrack(current + ')', left, right + 1, n, result); } } };

优势

  • 时间复杂度 O (4ⁿ/√n):符合卡特兰数时间规模,无多余无效路径。
  • 空间复杂度 O (n):递归栈深度最多为 2n,额外空间仅用于存储结果。
  • C++ 特性适配:通过引用传递 result 避免拷贝开销,string 拼接高效简洁。

三、解法二:动态规划(递推思想)

通过拆解子问题,利用已解决的 n-1 对括号组合推导 n 对的结果,适合喜欢递推思路的同学,C++ 中 vector 的嵌套存储让子问题结果复用更方便。

核心思路

  • 状态定义:dp [i] 表示 i 对括号的所有有效组合(vector<string>类型)。
  • 递推公式:dp [i] = "(" + dp [p] + ")" + dp [q],其中 p+q = i-1(p≥0,q≥0)。
    • 解释:每新增 1 对括号,可视为在 p 对括号外包裹 1 对括号,再拼接 q 对括号。
  • 初始状态:dp [0] = {""}(0 对括号对应空字符串)。

代码实现(C++)

#include <vector> #include <string> using namespace std; class Solution { public: vector<string> generateParenthesis(int n) { // dp[i]存储i对括号的所有有效组合 vector<vector<string>> dp(n + 1); dp[0] = {""}; // 初始状态:0对括号为空字符串 // 递推计算1到n对括号的组合 for (int i = 1; i <= n; ++i) { // 遍历所有可能的p(q = i-1 - p) for (int p = 0; p < i; ++p) { int q = i - 1 - p; // 拼接所有p和q的组合 for (const string& strP : dp[p]) { for (const string& strQ : dp[q]) { dp[i].push_back("(" + strP + ")" + strQ); } } } } return dp[n]; } };

优势

  • 逻辑直观:通过子问题拼接得到结果,无需递归,避免栈溢出风险。
  • 可复用性强:dp 数组存储了所有小于 n 的结果,便于后续扩展(如统计组合数、筛选特定格式组合)。
  • C++ 容器适配:vector 的动态扩容特性完美适配不同规模的结果存储。

四、两种解法对比与实战建议

解法时间复杂度空间复杂度适用场景
回溯算法O(4ⁿ/√n)O(n)面试首选(代码简洁)
动态规划O(4ⁿ/√n)O(4ⁿ/√n)需复用子问题结果时

实战建议:

  1. 面试中优先写回溯算法,C++ 代码仅需一个辅助函数,逻辑清晰易解释。
  2. 若面试官追问非递归解法或优化方向,再补充动态规划思路。
  3. 核心约束「左括号数≥右括号数」是有效组合的关键,务必牢记。
  4. 代码可直接运行:包含必要头文件和类结构,LeetCode 提交即可通过。

五、总结

括号生成问题的核心是「有效约束」和「组合遍历」,C++ 实现中,回溯算法利用递归 + 剪枝高效筛选路径,动态规划借助 vector 容器实现子问题递推。两种解法均围绕卡特兰数的数学本质,掌握后可举一反三解决同类组合问题(如合法括号计数、括号匹配检查等)。

建议先手动模拟 n=2、n=3 的生成过程,再对照代码理解逻辑,最后自己动手实现一遍。如果有优化思路或其他解法,欢迎在评论区交流~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/23 17:55:41

BetaFlight代码解析(20)—屏幕显示(OSD)

目的和范围屏幕显示 (OSD) 系统可在视频画面上实时叠加飞行信息&#xff0c;并提供飞行后统计信息。本文档涵盖 OSD 架构、元件系统、配置管理和警告机制。系统架构OSD系统由多个相互连接的子系统组成&#xff0c;这些子系统协同工作&#xff0c;提供全面的飞行信息显示&#x…

作者头像 李华
网站建设 2026/5/22 10:01:44

Elasticsearch 领域特定语言DSL

添加字段 PUT /es_order_info_1/_mapping {"properties": {"pjKKKKTime": {"type": "date","format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis||yyyy-MM-ddTHH:mm:ss.SSSXXX"},"otherTime": {…

作者头像 李华
网站建设 2026/5/24 0:22:06

AgenticSeek:本地AI代理如何彻底改变你的工作流

AgenticSeek&#xff1a;本地AI代理如何彻底改变你的工作流 【免费下载链接】agenticSeek A open, local Manus AI alternative. Powered with Deepseek R1. No APIs, no $456 monthly bills. Enjoy an AI agent that reason, code, and browse with no worries. 项目地址: h…

作者头像 李华
网站建设 2026/5/23 22:50:33

MCP AI Agent部署必须掌握的8项核心技术,少一项都可能引发考场事故

第一章&#xff1a;MCP AI Agent部署的考试案例概述在现代自动化运维与智能监控场景中&#xff0c;MCP&#xff08;Monitoring and Control Platform&#xff09;AI Agent 的部署已成为保障系统稳定性的重要环节。本章通过一个典型的考试案例&#xff0c;展示如何在实际环境中完…

作者头像 李华
网站建设 2026/5/22 10:01:34

《jQuery Treeview》深度解析与应用指南

《jQuery Treeview》深度解析与应用指南 引言 随着Web技术的发展,用户界面设计越来越注重交互性和用户体验。jQuery Treeview作为一种流行的树形菜单插件,在网页设计中发挥着重要作用。本文将深入解析jQuery Treeview的原理、应用场景以及如何在实际项目中使用它,旨在帮助…

作者头像 李华