【一篇文章学会使用从暴力法=>记忆化搜索=>动态规划以及栈的多种方法来实现LeetCode 32题最长有效括号问题】

news2024/12/23 20:49:44

在这里插入图片描述

🚀 算法题 🚀

🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀
🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨
🌲 作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎
🌲 恭喜你发现一枚宝藏博主,赶快收入囊中吧🌻
🌲 人生如棋,我愿为卒,行动虽慢,可谁曾见我后退一步?🎯🎯

🚀 算法题 🚀

在这里插入图片描述

🍔 目录

    • 🚩 题目链接
    • ⛲ 题目描述
    • 🌟 求解思路&实现代码&运行结果
      • ⚡ 暴力法
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • ⚡ 记忆化搜索
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • ⚡ 动态规划
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • ⚡ 栈
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
    • 🍋 总结
    • 💬 共勉

🚩 题目链接

  • 32. 最长有效括号

⛲ 题目描述

给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入:s = “(()”
输出:2
解释:最长有效括号子串是 “()”
示例 2:

输入:s = “)()())”
输出:4
解释:最长有效括号子串是 “()()”
示例 3:

输入:s = “”
输出:0

提示:

0 <= s.length <= 3 * 104
s[i] 为 ‘(’ 或 ‘)’

🌟 求解思路&实现代码&运行结果


⚡ 暴力法

🥦 求解思路

  1. 暴力法比较简单,我们枚举以每一个下标为开始位置,分别找到有效的(格式正确且连续)括号子串,找到所有情况的最大值即可。
  2. 问题来了?怎么找到以每一个位置为开始位置的最长连续有效子串呢?
  3. 我们可以来做一个简单的分析, 如果此时我们枚举到以cur位置为开始的最长有效的子串,此时的位置字符如果是’)‘,我们直接忽略,因为我们找不到以’)‘位置作为开始位置的有效子串;如果此时位置的字符是’(‘,那么我们有俩种情况可以进行判断,第一种去判断下一个位置的字符是’)‘吗?如果是,那么我们直接从cur+2去调用我们的递归函数,并且直接在原来的结果加2;但是,如果此时下一个位置的字符还是’(‘,那么此时我们就需要先找到以cur+1作为开始位置的最长连续有效子串长度len,然后去判断此时cur+len+1位置的元素是否为’)',如果是的话,我们直接从cur+len+2去调用我们的递归函数,并且直接在原来的结果加2。
  4. 思路我们有了,接下来就是具体代码的实现了。

🥦 实现代码

class Solution {
    public int longestValidParentheses(String s) {
        char[] arr=s.toCharArray();
        int max=0;
        for(int i=0;i<arr.length;i++){
            max=Math.max(max,process(i,arr));
        }
        return max;
    }

    public int process(int index,char[] arr){
        if(index>=arr.length) return 0;
        int max=0;
        if(arr[index]=='('){
            if(index+1<arr.length&&arr[index+1]==')'){
                max=Math.max(max,process(index+2,arr)+2);
            }else if(index+1<arr.length&&arr[index+1]=='('){
                int pre=process(index+1,arr);
                if(pre+index+1<arr.length&&arr[pre+index+1]==')'){
                    max=Math.max(max,pre+process(index+pre+2,arr)+2);
                }
            }
        }
        return max;
    }
}

🥦 运行结果

在这里插入图片描述


⚡ 记忆化搜索

🥦 求解思路

  1. 因为在递归的过程中,会重复的出现一些多次计算的结果,我们通过开辟一个数组,将结果提前缓存下来,算过的直接返回,避免重复计算,通过空间来去换我们的时间。

🥦 实现代码

class Solution {

    private int[] dp;

    public int longestValidParentheses(String s) {
        char[] arr=s.toCharArray();
        dp=new int[arr.length];
        Arrays.fill(dp,-1);
        int max=0;
        for(int i=0;i<arr.length;i++){
            max=Math.max(max,process(i,arr));
        }
        return max;
    }

    public int process(int index,char[] arr){
        if(index>=arr.length) return 0;
        if(dp[index]!=-1) return dp[index];
        int max=0;
        if(arr[index]=='('){
            if(index+1<arr.length&&arr[index+1]==')'){
                max=Math.max(max,process(index+2,arr)+2);
            }else if(index+1<arr.length&&arr[index+1]=='('){
                int pre=process(index+1,arr);
                if(pre+index+1<arr.length&&arr[pre+index+1]==')'){
                    max=Math.max(max,pre+process(index+pre+2,arr)+2);
                }
            }
        }
        return dp[index]=max;
    }
}

🥦 运行结果

我们发现,通过加一个缓存表,时间复杂度发生了翻天覆地的变化,真实不可思议!
在这里插入图片描述


⚡ 动态规划

🥦 求解思路

  1. 有了递归,有了记忆化搜索,接下来就是动态规划了,直接上手。

🥦 实现代码

class Solution {

    private int[] dp;

    public int longestValidParentheses(String s) {
        char[] arr=s.toCharArray();
        int n=arr.length;
        dp=new int[n+10];
        int ans=0;
        for(int index=n-1;index>=0;index--){
            int max=0;
            if(arr[index]=='('){
                if(index+1<arr.length&&arr[index+1]==')'){
                    max=Math.max(max,dp[index+2]+2);
                }else if(index+1<arr.length&&arr[index+1]=='('){
                    int pre=dp[index+1];
                    if(pre+index+1<arr.length&&arr[pre+index+1]==')'){
                        max=Math.max(max,pre+dp[index+pre+2]+2);
                    }
                }
            }
            dp[index]=max;
            ans=Math.max(ans,dp[index]);
        }
        return ans;
    }
}

🥦 运行结果

在这里插入图片描述


⚡ 栈

🥦 求解思路

已知每个有限的括号字符串必须是连续的,那么可以用栈来寻找以某个字符结尾最长的有限长度。
将栈底保存为最后一个未被匹配的右括号下标。

  1. 若当前字符为’(',直接将坐标放入栈中。
  2. 若当前字符为’)‘,先弹出栈顶坐标,若弹出后栈顶为空,那么代表这个’)'未被匹配,放入栈中;若栈不为空,那么代表已经匹配了,这时候统计它的有限长度为i-栈顶坐标。

🥦 实现代码

class Solution {
    public int longestValidParentheses(String s) {
        int n = s.length(), ans = 0;
        char[] arr = s.toCharArray();
        Deque<Integer> stack = new ArrayDeque<>();
        stack.push(-1);
        for (int i = 0; i < n; i++) {
            if (arr[i] == '('){
                stack.push(i);
            }
            else {
                stack.pop();
                if (stack.isEmpty()) {
                    stack.push(i);
                } else {
                    ans = Math.max(ans, i - stack.peek());              
                }
            }
        }
        return ans;
    }
}

🥦 运行结果

在这里插入图片描述


🍋 总结

本文介绍了四种解法来解决 LeetCode 32 题,即最长有效括号问题。循序渐进的引导大家从暴力法=>记忆化搜索=>动态规划以及栈的多种方法来实现最长有效括号问题。在实际应用中,可以根据具体情况来选择最合适的方法。

💬 共勉

最后,我想和大家分享一句一直激励我的座右铭,希望可以与大家共勉!

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/466864.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字IC入门教程

第一节课 linux命令 文件命令 man 查询指令的作用 如 man cd ls 列出当前文件和文件夹的名字&#xff08;list the directory and files&#xff09; ls -a 把隐藏的文件和文件夹也显示出来 &#xff08;list all&#xff09; ls -l 把文件的属性&#xff08;读写&…

如何设置ddns动态域名实现内网发布外网

在本地搭建好服务器&#xff0c;部署好web网站或其他应用后&#xff0c;需要设置动态域名服务ddns&#xff0c;将主机的内网IP端口映射到外网访问&#xff0c;才能实现在外网访问内网。今天小编就和大家分享一下内网发布外网方案&#xff0c;即如何设置ddns动态域名服务实现外网…

Docker compose 制作 LNMP 镜像

目录 第一章.Nginx镜像 1.1安装环境部署 1.2.nginx镜像容器的配置 第二章.php镜像的安装部署 2.1.文件配置 第三章.mysql镜像的安装部署 3.1.文件配置 第四章.配置网页 4.1.进入容器mysql 4.2.浏览器访问&#xff1a; 第一章.Nginx镜像 1.1安装环境部署 systemctl s…

十四、51单片机之AD转换

1、AD相关简介 1.1、什么是AD转换&#xff1f; (1)A是指analog、模拟的&#xff1b;D是指digital、数字的。 (2)现实世界是模拟的&#xff0c;连续分布的&#xff0c;无法被分成有限份&#xff1b;计算机世界是数字的&#xff0c;离散分布的&#xff0c;是可以被分成有限份的…

Springboot +Flowable,详细解释啥叫流程实例(二)

一.简介 上一篇中学习了Flowable 中的流程模板&#xff08;流程定义&#xff09;的部署问题&#xff0c;这一篇来学习什么叫流程实例。 部署之后的流程模板&#xff0c;还不能直接运行&#xff0c;例如我们部署了一个请假流程&#xff0c;现在 张三想要请假&#xff0c;他就需…

交叉小波变换(cross wavelet transform)是什么?

小波变换可以很好的在时频域中分析单个信号的瞬态和突变等时变特性&#xff0c;交叉小波变换是在小波变换的基础上提出的&#xff0c; 主要用来处理两个信号之间的相关程度。传统的互相关分析方法&#xff0c; 是通过傅里叶变换将信号从时域上转换到频域上&#xff0c;然后在频…

JavaScript实现输入数值求运算符的值

以下为a&#xff0c;a--&#xff0c;--a&#xff0c;a等运算符实现结果的代码 目录 前言 一、运算符&#xff08;x&#xff09; 2.1运行流程及思想 2.2代码段 2.3运行截图 二、运算符&#xff08;--x&#xff09; 3.1运行流程及思想 3.2代码段 3.3运行截图 三、输入数…

论文阅读 (88):Adversarial Examples for Semantic Segmentation and Object Detection

文章目录 1. 概述2 算法2.1 稠密对抗生成2.2 选择用于检测的输入提案 1. 概述 题目&#xff1a;用于语义分割和目标检测的对抗样本 核心点&#xff1a;将对抗性样本的概念扩展到语义分割和对象检测&#xff0c;并提出稠密对抗生成算法 (Dense adversary generation, DAG)。 引…

Python每日一练(20230427)

目录 1. 三数之和 &#x1f31f;&#x1f31f; 2. 编辑距离 &#x1f31f;&#x1f31f;&#x1f31f; 3. 翻转字符串里的单词 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏…

无人机监控交通流量实时传输路况智慧交通系统说明

项目介绍&#xff1a; “现在五星花园环岛通行状况良好&#xff0c;涪江路双向的通行状况也未出现拥堵&#xff0c;接送考生的车辆可以畅通行驶……”昨日上午 8 点 20 分&#xff0c;FM91.5南充交通音乐广播首次启用遥控无人飞行器服务考生。对市区易堵路段&#xff0c;特别是…

学成在线笔记+踩坑(10)——课程搜索、课程发布时同步索引库。

导航&#xff1a; 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题_java黑马笔记 目录 1 【检索模块】需求分析 1.1 全文检索介绍 1.2 业务流程 1.2.1、课程发布时索引库里新增一条记录 1.2.2、课程搜索 2 准…

Matlab论文插图绘制模板第88期—无向图/图论网络图

在之前的文章中&#xff0c;分享了Matlab线图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一种特殊的线图&#xff1a;无向图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下载。有需要的朋…

FreeRTOS 信号量(三) ------ 优先级翻转

一、优先级翻转 (1) 任务 H 和任务 M 处于挂起状态&#xff0c;等待某一事件的发生&#xff0c;任务 L 正在运行。 (2) 某一时刻任务 L 想要访问共享资源&#xff0c;在此之前它必须先获得对应该资源的信号量。 (3) 任务 L 获得信号量并开始使用该共享资源。 (4) 由于任务 H…

mysql慢查询日志

概念 MySQL的慢查询日志是MySQL提供的一种日志记录&#xff0c;它用来记录在MySQL中响应时间超过阀值的语句&#xff0c;具体指运行时间超过long_query_time值的SQL&#xff0c;则会被记录到慢查询日志中。long_query_time的默认值为10&#xff0c;意思是运行10秒以上的语句。…

计算机图形学 | 投影变化

计算机图形学 | 投影变化 计算机图形学 | 投影变化7.1 有趣的投影投影的概念平行投影正投影斜投影 透视投影 7.2 规范化的投影变换观察的要素观察空间规范化的投影变换 华中科技大学《计算机图形学》课程 MOOC地址&#xff1a;计算机图形学&#xff08;HUST&#xff09; 计算…

Flink时间和窗口

事件时间 到达时间 处理时间 水位线 1.有序流 2. 无序流 水位线离源越近越好 Flink 自带水位线 有序 WatermarkStrategy.<Event>forMonotonousTimestamps() 或者实现WatermarkStrategy接口 水位线生成 时间字段 乱序 WatermarkStrategy.<Event>forBoundedOut…

【MySQL高级】——InnoDB索引MyISAM索引

一、索引概述 MySQL官方对索引的定义为&#xff1a;索引&#xff08;Index&#xff09;是帮助MySQL高效获取数据的数据结构。 索引的本质&#xff1a;索引是数据结构。你可以简单理解为“排好序的快速查找数据结构”&#xff0c;满足特定查找算法。 这些数据结构以某种方式指向…

Redis基础知识概述

Redis基础知识概述 文章目录 Redis基础知识概述一、Redis简介二、NoSQL技术三、Redis的高并发和快速原因四、Redis为什么是单线程的 五、单线程的优劣势1、优势2、劣势 六、Redis高并发总结七、在java中使用Redis1、添加Jedis依赖 八、Redis在Java Web中的应用1、存储缓存用的数…

亿发软件:按需定制ERP管理解决方案,更合适的企业智能管理软件

亿发软件&#xff1a;按需定制ERP管理解决方案&#xff0c;更合适的企业智能管理软件 在当今瞬息万变的商业环境中&#xff0c;企业面临着新的挑战和机遇。随着国内传统市场的衰落和国际化发展的加速&#xff0c;市场竞争日趋激烈&#xff0c;企业必须寻找新的创新和适应方式才…

Linux基本指令和操作(2)

目录 一. 适配符 * 二. man指令 -- 查看手册 三. echo指令 -- 输出字符串到文件 四. cp指令 -- 复制 五. mv指令 -- 重命名或移动文件&#xff08;剪切&#xff09; 六. which指令 -- 查看指令所在的路径 七. alis指令 -- 指令重命名 八. cat指令 -- 输出文件内容 九…