0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一道LeetCode的多种解法

算法与数据结构 来源:算法与数据结构 2020-05-06 10:39 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

Leetcode 最新上线了手机版 APP,今天蹲坑的时候随手翻了一道题,一道和栈有关的题目,大概知道了解题思路,就点开了题解准备看看别人是如何写代码的,没想到最后一种解法让我感觉自己的智商受到了碾压。

题目描述

给定一个只包含'('和')'的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入:"(()" 输出:2 解释:最长有效括号子串为"()"

示例 2:

输入:")()())" 输出:4 解释:最长有效括号子串为"()()"

题目解析

解法一:栈

一开始看到这个题目,有点熟悉的感觉:相当于是 LeetCode 第 20 题有效的括号的升级版。

想到这立马尝试借助栈这个数据结构去解决。

括号相关的问题首先可以尝试使用栈这个数据结构去解决,至于原因,想一想应该不难理解,如果进来一个右括号,也就是 ')',它会和之前最后一次遍历到的左括号匹配,栈的先进后出的特性保证了这一要求。

对于这道题目,因为我们要求的是子串的长度,因此我们可以考虑在栈中保存index,这样子我们不仅可以通过index找到对应的括号,还可以借此来求长度,我们的思路可以分为下面几步:

1、从左到右遍历输入的字符串

2、如果遇到的是'(',意味着这并不能和前面遍历过的部分组成合法答案,此时我们只需要把当前index入栈即可

3、如果遇到的是')',这时我们就要看栈顶保存的元素了,这里就会有几种情况:

栈顶保存的是'(',表示当前元素和栈顶元素可以配对,这个时候我们需要把栈顶元素弹出栈,记录答案则记录当前index和弹出配对元素后的新栈顶index之间的距离,这个地方是重点,如果不理解,你可以思考下面两个例子:

"((()()" "((())"

栈顶保存的是')',如果是这种情况,表示前面没有可配对的 '(',我们此时还是需要把当前index入栈,原因是

我们确定距离需要知道边界,如果不理解,还是有两个例子供你参考:

"))(())" "())()()"

栈是空的,当然在第一种情况中,你弹出栈顶元素后也会使得栈变空,为了避免这种情况,我们可以在最开始的时候推一个-1入栈,这样可以节省我们的判断次数,并且当栈中的没有元素的时候,我们也可以用这个-1来计算当前子串的长度,你可以参考下面这两个例子:

"()" "()(())"

代码实现

publicintlongestValidParentheses(Strings){ if(s==null||s.length()==0){ return0; } intn=s.length(); char[]sArr=s.toCharArray(); Stackstack=newStack<>(); intresult=0; //-1入栈用于处理边界条件 stack.push(-1); for(inti=0;i< n; ++i) {         // stack.size() >1表示栈不为空,而且我们必须保证栈顶元素是'(' if(sArr[i]==')'&&stack.size()>1&&sArr[stack.peek()]=='('){ //配对的'('出栈 stack.pop(); //记录长度 result=Math.max(result,i-stack.peek()); }else{//其他情况,直接将当前位置入栈 stack.push(i); } } returnresult; }

解法二:动态规划

如果用栈来解决的话,这道题思路差不多就是这样。考虑到前不久一直聊动态规划,于是试了一下用把它归纳到序列型动态规划来求解。

动态规划之空间优化与总结回顾

我们可以定义dp[i] 表示的是 str[0…i] 的答案,思路其实和前面很类似:

1、从左到右遍历输入的字符串

2、如果遇到的是 '(',意味着这并不能和前面遍历过的部分组成合法答案,因为 dp 状态数组中记录的是答案,这个时候说明 dp[i] = 0,也就是不用做任何记录

3、如果遇到的是 ')',这时我们还是需要往前看:

如果 str[i - 1] 是 '(',那么 dp[i] = dp[i - 2] + 2

如果 str[i - 1] 是 ')',这表示 str[i - 1] 已经配对了,因此我们还要继续往前看,从当前位置往左,看第一个没有被配对的 '(',怎么找这个位置呢,这里我们就可以利用 dp[i - 1] 这个信息,dp[i - 1] 表示的是之前匹配的长度,那么 :

i - dp[i - 1] - 1表示的就是从当前位置往左,第一个没有被配对的位置

如果位置 i 和 位置 i - dp[i - 1] - 1 配对后,我们可以看看当前的序列是否可以和之前匹配的序列链接起来,也就是加上 dp[i - dp[i - 1] - 2]

代码实现

publicintlongestValidParentheses(Strings){ if(s==null||s.length()==0){ return0; } intn=s.length(); char[]sArr=s.toCharArray(); int[]dp=newint[n]; intresult=0; for(inti=1;i< n; ++i) {         if (sArr[i] == ')') {             // 如果前一个位置是 '(',直接配对             if (sArr[i - 1] == '(') {                 dp[i] = (i >=2?dp[i-2]:0)+2; } //前一个位置是')' //我们从当前位置往左看,如果第一个没有被匹配的位置是'(' //表明当前位置是可以被匹配的 elseif(i-dp[i-1]-1>=0&&sArr[i-dp[i-1]-1]=='('){ //这里其实是dp[i]=i-(i-dp[i-1]-1)+1=dp[i-1]+2 //但是我们还需要考虑之前的答案,也就是dp[i-dp[i-1]-2] //首先判断i-dp[i-1]-2是否越界 //如果没有越界就将其加上 dp[i]=dp[i-1]+2; if(i-dp[i-1]>=2){ dp[i]+=dp[i-dp[i-1]-2]; } } result=Math.max(result,dp[i]); } } returnresult; }

两种方法时空复杂度都是 O(n),解法也有相似之处,只是说切题点不一样。

正当我美滋滋时,突然看到另外一种解法,让我感觉自己的智商受到了碾压:不需要额外的空间,空间复杂度是 O(1)!

解法三:借助变量

使用了两个变量 Left 和 Right,分别用来记录到当前位置时左括号和右括号的出现次数。

当遇到左括号时,Left 自增 1,右括号时 Right 自增1。

对于最长有效的括号的子串,一定是左括号等于右括号的情况,此时就可以更新结果 res 了,一旦右括号数量超过左括号数量了,说明当前位置不能组成合法括号子串,Left 和 Right 重置为 0。

但是对于这种情况 "(()" 时,在遍历结束时左右子括号数都不相等,此时没法更新结果 res,但其实正确答案是 2,怎么处理这种情况呢?

答案是再反向遍历一遍,采取类似的机制,稍有不同的是此时若 Left 大于 Right 了,则重置 0,这样就可以涵盖所有情况。

代码实现

//代码来源:https://leetcode-cn.com/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode/ publicclassSolution{ publicintlongestValidParentheses(Strings){ intleft=0,right=0,maxlength=0; for(inti=0;i< s.length(); i++) {             if (s.charAt(i) == '(') {                 left++;             } else {                 right++;             }             if (left == right) {                 maxlength = Math.max(maxlength, 2 * right);             } else if (right >=left){ left=right=0; } } left=right=0; for(inti=s.length()-1;i>=0;i--){ if(s.charAt(i)=='('){ left++; }else{ right++; } if(left==right){ maxlength=Math.max(maxlength,2*left); }elseif(left>=right){ left=right=0; } } returnmaxlength; } }

事实上,我在利用解法一求解完这道题目后还怡然自得,认为这道题目最简单的解法就是借助栈这种数据结构,没想到还有解法三这么巧妙的解法。。。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据结构
    +关注

    关注

    3

    文章

    573

    浏览量

    41674
  • leetcode
    +关注

    关注

    0

    文章

    20

    浏览量

    2557

原文标题:一道 LeetCode 的多种解法,打消了我的自以为是!

文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    芯片的“第一道体检”:文读懂CP测试,半导体人必看!

    在芯片从晶圆到成品的漫长旅程里,有一道看不见却至关重要的关卡——CP测试。它被称为芯片良率的“守门员”、封装成本的“节流阀”,更是半导体产业链里前端制造与后端封测之间的关键枢纽。今天这篇,用通俗
    的头像 发表于 04-17 10:03 305次阅读
    芯片的“第<b class='flag-5'>一道</b>体检”:<b class='flag-5'>一</b>文读懂CP测试,半导体人必看!

    深入解析AD5737:款高性能四通电流输出DAC

    深入解析AD5737:款高性能四通电流输出DAC 在工业过程控制领域,精确的电流输出对于系统的稳定运行至关重要。AD5737作为款四通电流输出DAC,凭借其出色的性能和丰富的功
    的头像 发表于 04-13 09:55 343次阅读

    FT 测试:芯片出货前的最后一道闸门

    在封装流程里FT是个挺微妙的工序。它排在最后,却经常最先被怀疑:良率掉了→是不是FT卡严了?客诉来了→终测有没有漏检?批量异常→是不是测试程序问题?但在产线待久了会慢慢明白句话:FT通常不是
    的头像 发表于 03-27 10:02 181次阅读
    FT 测试:芯片出货前的最后<b class='flag-5'>一道</b>闸门

    EOL测试系统——电池包下线前的最后一道品质防线

    在储能电池包的生产线上,EOL测试系统 是产品交付前的最后一道关口,也是最重要的品质防线。EOL测试的全面性与可靠性,直接决定了流入市场的储能产品是否存在早期失效风险。 个完整的电池包EOL测试
    的头像 发表于 03-23 16:40 351次阅读
    EOL测试系统——电池包下线前的最后<b class='flag-5'>一道</b>品质防线

    海康观澜大模型助力公共安全领域效率提升

    海康观澜大模型再拓新场景,用科技为孩子的上学路筑起一道坚实防线。
    的头像 发表于 03-18 17:35 843次阅读

    红区破局之道:为什么防逆流装置是“第一道防线”?

    当之无愧的“第一道防线”。它不像四可装置那样兼具“可观可测、可控可调”的全链条能力,却能以最直接、最精准的方式,守住红区光伏并网的安全底线,为后续精细化管控、高效消纳筑牢基础——没有这道防线,红区光伏的合规运营、收益保障都将无从谈起。
    的头像 发表于 03-16 15:32 769次阅读
    红区破局之道:为什么防逆流装置是“第<b class='flag-5'>一道</b>防线”?

    3秒响应、实时告警!智能井盖如何成为城市安全的“第一道防线”?

    IP68防护、-40℃~80℃宽温运行及10年超长续航,支持自定义报警阈值与多级告警机制,大幅降低误报率。作为城市物联网感知层的关键节点,智能井盖已融入智慧城管与应急管理体系,成为守护市民脚下安全的“第一道防线”。
    的头像 发表于 12-09 11:57 457次阅读
    3秒响应、实时告警!智能井盖如何成为城市安全的“第<b class='flag-5'>一道</b>防线”?

    车载屏幕基础可靠性功能测试:守护智能座舱的“第一道防线”

    车载屏幕的基础可靠性功能测试,绝非简单的“点亮屏幕、点几下看看”。它是个贯穿显示、触控、软件、硬件、环境、安全等多领域的系统工程。每块最终装车的屏幕,其背后都是上述测试模块成千上万次严谨验证
    的头像 发表于 12-04 09:59 2090次阅读
    车载屏幕基础可靠性功能测试:守护智能座舱的“第<b class='flag-5'>一道</b>防线”

    点焊机如何成为动力电池安全的第一道防线?

    在动力电池制造领域,电池点焊机的价值远不止于“连接”。它是在电池包这精密系统中,为电流构建可靠通路、为结构提供机械固持的核心装备。其工作的成败,直接锚定了整个电池包的安全性与使用寿命。 动力电池包
    的头像 发表于 11-27 09:55 561次阅读

    不间断电源(UPS):电力保障的“最后一道防线”

    (UninterruptiblePowerSupply,简称UPS)作为电力保障的“最后一道防线”,通过储能装置与智能转换技术,在市电中断时实现零切换时间供电,成为现代社会的“电力守护者”。、UP
    的头像 发表于 10-29 09:02 1929次阅读
    不间断电源(UPS):电力保障的“最后<b class='flag-5'>一道</b>防线”

    施耐德电气SmartCool助力金融行业数据中心节能降耗

    绿色数据中心的极致节能不是在和电费较劲,而是在回答一道时代命题。
    的头像 发表于 09-25 16:08 848次阅读

    铅酸蓄电池在线监测:为关键基础设施筑牢“最后一道防线”

    在数据中心、通信基站、轨道交通等关键应用场景中,蓄电池组往往是供电系统的“最后一道屏障”。旦蓄电池出现故障,可能导致系统断电、数据丢失甚至设备损坏,带来不可估量的经济损失和安全风险。因此,对蓄电池
    的头像 发表于 09-23 09:31 776次阅读
    铅酸蓄电池在线监测:为关键基础设施筑牢“最后<b class='flag-5'>一道</b>防线”

    顶坚国产防爆手持终端如何成为石化企业安全生产的第一道防线

    顶坚国产防爆手持终端之所以能成为石化企业安全生产的第一道防线,源于其通过防爆设计、功能集成、实时交互与系统协同,从物理安全、功能安全、管理安全、应急安全等维度,覆盖了安全生产的全流程(预防、监测
    的头像 发表于 08-26 10:31 976次阅读
    顶坚国产防爆手持终端如何成为石化企业安全生产的第<b class='flag-5'>一道</b>防线

    测试测量仪器对SMA公头的性能要求​

    对测试测量仪器而言,SMA 公头是 “数据入口”,性能直接决定结果可信度。德索从材料到工艺的全流程把控,让每个公头都成为精准测量的第一道保障。选择德索,就是给测试数据上了一道 “保险栓”。
    的头像 发表于 08-22 17:04 857次阅读
    测试测量仪器对SMA公头的性能要求​

    聚徽制造业专属工业触摸屏:精准控制每一道工序,提升生产精度

    在制造业竞争日益激烈的当下,产品质量与生产效率成为企业立足市场的关键,而生产精度则是保障产品质量的核心要素。制造业专属工业触摸屏凭借其独特的功能与技术优势,深度融入生产的每一道工序,实现对生
    的头像 发表于 05-16 15:50 850次阅读