https://leetcode.com/problems/maximum-nesting-depth-of-two-valid-parentheses-strings/
题意
给一个仅由左右括号组成的字符串,并且该字符串中的左右括号一定能被完全匹配,例如以下的字符串都属于可被完全匹配:
()
(())
()()
(()())
定义一个概念为字符串的 depth,depth 的定义如下:
空串的 depth 为 0
假设字符串为一块能完全匹配的括号串,例如 (...) ,depth = 1 + ...的 depth
假设字符串由多块能完整匹配的括号串组成,例如 (...)(...)(...),depth = 每块串中的最大值;例如:
(()) 的 depth 为 2
()(()) 的 depth 为 2
()() 的 depth 为 1
现在把字符串中的每个字符,要么划分到 A,要么划分到 B,并且要满足以下的条件:
使得 A 是一个能完全匹配的字符串
使得 B 是一个能完全匹配的字符串
属于 A 的字符在原来的字符串中的位置不必连续,但不能改变其相对位置;B 同理
分别求出 A,B 的 depth,两个 depth 的较大值为这种划分方案的 depth
求出一种划分方案,使得划分方案的 depth 最小
class Solution {public: vector<int> maxDepthAfterSplit(string seq) { int n = seq.length(); std::vector<int> ret(n); int depth[2] = {0, 0}; int used[2] = {0, 0}; std::stack<int> stk; auto update = [&depth, &ret](int i, int type) { ret[i] = type; ++depth[type]; }; for (int i = 0; i < n; ++i) { if (seq[i] == '(') { stk.push(i); if (depth[0] < depth[1]) update(i, 0); else if (depth[1] < depth[0]) update(i, 1); else { if (!used[0]) update(i, 0); else update(i, 1); } } else { int idx = stk.top(); stk.pop(); ret[i] = ret[idx]; --depth[ret[i]]; } } return ret; }};
这个问题最重要是要理解 depth 的定义,稍加分析可知,字符串的 depth 等于最大的连续左括号的个数
如果要构造一种划分方案,使得 A B 的 depth 都尽量小,本质就是减少连续的左括号的数量
因此我们可以基于贪心的思想,可以设计一种,一边记录 A B 当前的 depth,一边决定下一步的构造方案
当把一个左括号放入 A 或 B 时,会使得 A 或 B 当前的 depth 增 1
当把一个右括号放入 A 或 B 时,会使得 A 或 B 当前的 depth 减 1
每次遇到一个左括号,判断一个哪边的 depth 较小,优先放入较小的那边
当遇到右括号时,能与它匹配的左括号是唯一固定的,可以确定应该放入 A 还是 B
PapaMelon, 让算法好玩
关注 B 站 不爱睡觉的大猪
获取更好的视频体验
加入 PapaMelon 算法社区微信群
一起学习进步