leetcode 贪心_LeetCode | 贪心 | 又见括号匹配问题

358a5910c78f360d718537a2f33f1886.png

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, 让算法好玩

c9280e7971d31f05eebf429fb8f7c309.png


关注 B 站 不爱睡觉的大猪

获取更好的视频体验

f9075bd76effbc74a8a64f84ffe862f5.png


加入 PapaMelon 算法社区微信群

一起学习进步

7c5a3221d9ffadc8f5a850207edd317e.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值