题目

一个括号字符串是只由 '('')' 组成的 非空 字符串。如果一个字符串满足下面 任意 一个条件,那么它就是有效的:

  • 字符串为 ().
  • 它可以表示为 ABAB 连接),其中AB 都是有效括号字符串。
  • 它可以表示为 (A) ,其中 A 是一个有效括号字符串。

给你一个括号字符串 s 和一个字符串 locked ,两者长度都为 nlocked 是一个二进制字符串,只包含 '0''1' 。对于 locked每一个 下标 i

  • 如果 locked[i]'1' ,你 不能 改变 s[i]
  • 如果 locked[i]'0' ,你 可以s[i] 变为 '(' 或者 ')'

如果你可以将 s 变为有效括号字符串,请你返回 true ,否则返回 false

示例 1:

  1. 输入:s = "))()))", locked = "010100"
  2. 输出:true
  3. 解释:locked[1] == '1' locked[3] == '1' ,所以我们无法改变 s[1] 或者 s[3]
  4. 我们可以将 s[0] s[4] 变为 '(' ,不改变 s[2] s[5] ,使 s 变为有效字符串。

示例 2:

  1. 输入:s = "()()", locked = "0000"
  2. 输出:true
  3. 解释:我们不需要做任何改变,因为 s 已经是有效字符串了。

示例 3:

  1. 输入:s = ")", locked = "0"
  2. 输出:false
  3. 解释:locked 允许改变 s[0]
  4. 但无论将 s[0] 变为 '(' 或者 ')' 都无法使 s 变为有效字符串。

示例 4:

  1. 输入:s = "(((())(((())", locked = "111111010111"
  2. 输出:true
  3. 解释:locked 允许我们改变 s[6] s[8]。
  4. 我们将 s[6] s[8] 改为 ')' 使 s 变为有效字符串。

提示:

  • n == s.length == locked.length
  • 1 <= n <= 105
  • s[i] 要么是 '(' 要么是 ')'
  • locked[i] 要么是 '0' 要么是 '1'

思路

​ 一看到题目是判断合法括号,就想到了这题好像我会啊,不就是用栈来判断,左括号压栈,右括号出栈,如果栈最后为空,且中间也没有不够用(遇到右括号,但是栈为空导致无元素可以弹出),那么就是合法括号。

​ 如果只有一种括号,这里还可以优化,不需要真正去压栈和出栈,用一个变量,左括号就+1,右括号就-1,直到最后结果为0,且中间不存在任何时候是小于0的情况,就是合法括号。

​ 本题略微有一些变化,求的是是否可以通过改变原始字符串,变成合法括号。一个合法的括号,必然满足如下条件:

  • 长度为偶数,其中一半是左括号,一半是右括号
  • 任意一个前缀,都满足左括号数量大于等于右括号数量
  • 任意一个后缀,都满足右括号数量大于等于左括号数量

​ 只有locked为1的位置,原始括号才不可变,其他位置的原始括号是可变的,即不用管原始括号是什么。具体操作上,我们可以做如下3步校验:

  • 长度为偶数,如果为奇数,肯定不是合法的
  • 对于任意一个前缀,贪心的认为,任何非locked的位置,都变成左括号的情况下,都满足左括号数量大于等于右括号数量
  • 对于任意一个后缀,贪心的认为,任何非locked的位置,都变成右括号的情况下,都满足右号数量大于等于左括号数量

代码

  1. public boolean canBeValid(String s, String locked) {
  2. // 长度为奇数,不可能是合法括号
  3. int n = s.length();
  4. if ((n & 1) == 1) {
  5. return false;
  6. }
  7. char[] chars = s.toCharArray();
  8. char[] lockedChars = locked.toCharArray();
  9. // 任意一个前缀,左括号都大于等于右括号
  10. int left = 0;
  11. for (int i = 0; i < n; i++) {
  12. if (lockedChars[i] == '1' && chars[i] == ')') {
  13. left--;
  14. } else {
  15. left++;
  16. }
  17. if (left < 0) {
  18. return false;
  19. }
  20. }
  21. // 任意一个后缀,右括号都大于等于左括号
  22. int right = 0;
  23. for (int i = n - 1; i >= 0; i--) {
  24. if (lockedChars[i] == '1' && chars[i] == '(') {
  25. right--;
  26. } else {
  27. right++;
  28. }
  29. if (right < 0) {
  30. return false;
  31. }
  32. }
  33. return true;
  34. }

耗时

leetcode每日一题:判断一个括号字符串是否有效的更多相关文章

  1. 【python】Leetcode每日一题-扰乱字符串

    [python]Leetcode每日一题-扰乱字符串 [题目描述] 使用下面描述的算法可以扰乱字符串 s 得到字符串 t : 如果字符串的长度为 1 ,算法停止 如果字符串的长度 > 1 ,执行 ...

  2. LeetCode 每日一题「判定字符是否唯一」

    我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 题目 ...

  3. 【JavaScript】Leetcode每日一题-平方数之和

    [JavaScript]Leetcode每日一题-平方数之和 [题目描述] 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c . 示例1: 输入:c = 5 ...

  4. 【JavaScript】【dp】Leetcode每日一题-解码方法

    [JavaScript]Leetcode每日一题-解码方法 [题目描述] 一条包含字母 A-Z 的消息通过以下映射进行了 编码 : 'A' -> 1 'B' -> 2 ... 'Z' -& ...

  5. 【JavaScript】【KMP】Leetcode每日一题-实现strStr()

    [JavaScript]Leetcode每日一题-实现strStr() [题目描述] 实现 strStr() 函数. 给你两个字符串 haystack 和 needle ,请你在 haystack 字 ...

  6. [LeetCode每日一题]81. 搜索旋转排序数组 II

    [LeetCode每日一题]81. 搜索旋转排序数组 II 问题 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 & ...

  7. 【python】Leetcode每日一题-存在重复元素3

    [python]Leetcode每日一题-存在重复元素3 [题目描述] 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] ...

  8. 【python】Leetcode每日一题-最大数

    [python]Leetcode每日一题-最大数 [题目描述] 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数. 注意:输出结果可能非常大,所以你需要返回一个 ...

  9. 【python】Leetcode每日一题-丑数

    [python]Leetcode每日一题-丑数 [题目描述] 给你一个整数 n ,请你判断 n 是否为 丑数 .如果是,返回 true :否则,返回 false . 丑数 就是只包含质因数 2.3 和 ...

  10. 【python】Leetcode每日一题-最长公共子序列

    [python]Leetcode每日一题-最长公共子序列 [题目描述] 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度.如果不存在 公共子序列 ,返回 0 . ...

随机推荐

  1. Solution -「CF 1290F」Making Shapes

    \(\mathscr{Description}\)   给定平面向量集 \(\newcommand{\vct}[1]{\boldsymbol{#1}}\{\vct v_n\}\),求从 \((0,0) ...

  2. CDS标准视图:维护通知数据 I_PMNotifMaintenanceData

    视图名称:维护通知数据 I_PMNotifMaintenanceData 视图类型:基础视图 视图代码: 点击查看代码 @EndUserText.label: 'Notification Mainte ...

  3. UWP Shadow 阴影

    参考文字: https://mtaulty.com/2016/08/10/windows-10-uwp-and-composition-light-and-shade/ <Grid Backgr ...

  4. jwt-shiro-springsecurity-oauth2对比

    1 实现token的方式概述 在cookie\session\token辨析一文已经知道了token这个概念,里面简单说明了token的组成就是数据+签名,给出了token实现身份验证的流程,并且详细 ...

  5. runoob-android

    https://www.runoob.com/android/android-tutorial.html https://www.runoob.com/w3cnote/android-tutorial ...

  6. VueJs(1)---操作指南

    [VueJs入门] 一.上手步骤 vue.js和jquery一样,只要引入vue.js就可以了. 1.创建一个Vue实例: 先引入Vue.js文件,然后new一个Vue的实例即可.如下面的代码,通过& ...

  7. 一个月狂赚百万?DeepSeek爆火背后的"卖铲人"狂欢

    大家好,我是郭顺发,一个白天敲代码晚上写博客的独立开发者.最近有个叫DeepSeek R1的AI模型火得离谱--不是因为它技术多逆天,而是因为一堆人靠它一个月赚了几百万,而他们卖的东西...你绝对想不 ...

  8. Q:以非root用户编辑定时任务报错You are not allowed to use this program(crontab)

    编辑定时删除文件任务时报错 crontab -e 编辑定时任务时报错,如下图所示 问题原因:/etc/cron.allow中没有添加对应的用户名解决办法:切换到root用户,在/etc/cron.al ...

  9. 【忍者算法】从拉链到链表:探索有序链表的合并之道|LeetCode 21 合并两个有序链表

    从拉链到链表:探索有序链表的合并之道 生活中的合并 想象你正在整理两叠按日期排好序的收据.最自然的方式就是:拿起两叠收据,每次比较最上面的日期,选择日期较早的那张放入新的一叠中.这个简单的日常操作,恰 ...

  10. java list集合去重的两种方式