【算法练习】有趣的括号匹配问题(思路+ 图解 +优化)基于java实现

简介: 1.题目描述小洛看着一堆只包含’(‘和’)‘的括号序列犯愁了,小洛想知道这串序列里最长正确匹配的序列长度是多少,你能帮帮小洛吗?

1.题目描述

小洛看着一堆只包含’(‘和’)‘的括号序列犯愁了,小洛想知道这串序列里最长正确匹配的序列长度是多少,你能帮帮小洛吗?

输入

输入一个只包含’(‘与’)'的字符串,字符串长度n满足0<n≤50000

输出

输出一个数表示子串长度

数据范围

对于100%的数据,0<n≤50000

输入样例

((((())(

输出样例

4


2.问题分析

说到括号匹配问题,我们很容易想到利用栈来解决,但是直接使用栈来进行处理的话,你会发现,无法记录在入栈出栈过程中匹配的长度。因此,我们对栈进行优化,对于栈中存储的每个元素我们都把它当作一个结点,包含data(左括号或者右括号),以及标号值,用index表示。



对于一个序列"( ( ( ) ) ) ) )",首先我们将括号序列依次进行标号,分别为12345678我们让左括号直接入栈,遇到右括号则观察栈中栈顶元素是否为左括号,若是,则出栈;反之,则入栈。

反复进行入栈和出栈操作后,栈中只剩下标号为7、8的两个右括号,则最大匹配长度为7 - 0 - 1 = 6;




我们再来看一个序列"()()",标号分别为1234,进行入栈出栈操作后,最终栈中元素为0,此时最大匹配长度则为字符串的长度,即为4 - 0 = 4。


3.算法分析

对于执行后的栈,我们大致可以分为如下的三种情况:


栈为空:此时最大匹配长度为字符串的长度;

栈底为" ) ":此时隐藏一种匹配长度为栈底标号 - 0 - 1;

栈底为" ( ": 只需要比较任意相邻两个栈中元素标号的差,匹配长度为end - start - 1。

以题目的测试样例为例,输入字符串((((())(,最终剩余在栈中的为标号为1238的左括号,此时最大匹配长度为8 - 3 -1 = 4。


4.实现代码

这里简单对以上讨论的三种情况进行实现,详细可见注释内容。

import java.util.Scanner;
import java.util.Stack;
// 结点类,用于入栈元素的标号
class Node{
    char data;// 存储括号值
    int index;// 用于标号
    public Node(char data, int index){
        this.data = data;
        this.index = index;
    }
}
public class test03 {
    public static void main(String[] args) {
        Stack<Node> stack = new Stack<>(); // 入栈的每个元素都是带有标号的左括号,而匹配的长度则为两个相邻的左括号标号的差值-1
        Scanner in = new Scanner(System.in);
        String s = in.next();
        char[] strings = s.toCharArray();
        boolean flag = false;
        int temp = 0; // 临时储存
        // 遍历括号字符串
        int i; // 这里把i单独声明是为了扩大作用域便于end使用
        for ( i = 0 ; i < strings.length; i++) {
            // 遇到左括号入栈,栈中的标号以1为起点
            if(strings[i] == '('){
                stack.push(new Node(strings[i], i+1));
            }
            // 遇到右括号看栈内是否匹配
            if(strings[i] == ')'){
                if(stack.empty()){
                    // 处理)))这种情况
                    flag = true; // 说明栈是以右括号为栈底
                    temp = i+1;
                    stack.push(new Node(strings[i], i+1)); // 防止栈下溢
                }else{
                    // 匹配则出栈,不匹配则入栈
                    if(stack.peek().data == '('){
                        stack.pop();
                    }else{
                        stack.push(new Node(strings[i], i+1));
                    }
                }
            }
        }
        // 计算匹配长度
        int start = 0, length = 0, end = i+1;
        // 括号完全匹配,即栈中元素为0,则长度为字符串长度
        if(stack.empty())
            length = end - start - 1;
        while (!stack.empty()){
            // 栈中以右括号为栈底元素,需要记录一次栈底元素标号与0的差值
            if(flag){
                length = Math.max(temp - start -1, length);
            }
            // 栈中以左括号为栈底元素,只需要比较标号的差值
            start = stack.pop().index;
            //System.out.println("start = " + start);
            length = Math.max(end - start - 1, length);
            // 以start为新的end
            end = start;
        }
        // 输出结果
        System.out.println(length);
        in.close();
    }
}

5.实现结果

输入((((())(测试1



输入()()测试2


输入)))))测试3


6.代码优化

从上面的实现中发现,分为三种情况即单独对栈空的情况进行计算、使用了flag变量来判断栈底是否为右括号、单独对栈底为左括号的情况进行运算。虽然逻辑上没有问题,但是这样不仅多声明了变量,还使代码显得异常复杂。

那么有没有办法可以简化计算呢?

我们发现,只要先将一个标号为0的无关量入栈,这样无论何种情况,在进行最后一步“计算最大匹配长度”时,栈都不会为空,这样就不需要对栈空的情形进行单独讨论;不仅如此,我们存储的0无关量也可以解决右括号为栈底的情况,可以把无关量想成左括号,进行一般情况下的栈元素的标号差操作,即可求出匹配长度。


6.1 具体代码优化实现

import java.util.Scanner;
import java.util.Stack;
// 结点类,用于入栈元素的标号
class Node{
    char data;// 存储括号值
    int index;// 用于标号
    public Node(char data, int index){
        this.data = data;
        this.index = index;
    }
}
public class test03 {
    public static void main(String[] args) {
        Stack<Node> stack = new Stack<>(); // 入栈的每个元素都是带有标号的左括号,而匹配的长度则为两个相邻的左括号标号的差值-1
        Scanner in = new Scanner(System.in);
        String s = in.next();
        char[] strings = s.toCharArray();
        stack.push(new Node('0', 0));// 标号0位置存储一个无关量,便于计算
        // 遍历括号字符串
        int i; // 这里把i单独声明是为了扩大作用域便于end使用
        for ( i = 0 ; i < strings.length; i++) {
            // 遇到左括号入栈,栈中的标号以1为起点
            if(strings[i] == '('){
                stack.push(new Node(strings[i], i+1));
            }
            // 遇到右括号看栈内是否匹配
            if(strings[i] == ')'){
                if(stack.empty()){
                    stack.push(new Node(strings[i], i+1)); // 防止栈下溢
                }else{
                    // 匹配则出栈,不匹配则入栈
                    if(stack.peek().data == '('){
                        stack.pop();
                    }else{
                        stack.push(new Node(strings[i], i+1));
                    }
                }
            }
        }
        // 计算匹配长度
        int start = 0, length = 0, end = i+1;
        while (!stack.empty()){
            start = stack.pop().index;
            //System.out.println("start = " + start);
            length = Math.max(end - start - 1, length);
            // 以start为新的end
            end = start;
        }
        // 输出结果
        System.out.println(length);
        in.close();
    }
}


相关文章
|
8天前
|
机器学习/深度学习 算法
基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真
本项目基于改进遗传优化的BP神经网络进行金融序列预测,使用MATLAB2022A实现。通过对比BP神经网络、遗传优化BP神经网络及改进遗传优化BP神经网络,展示了三者的误差和预测曲线差异。核心程序结合遗传算法(GA)与BP神经网络,利用GA优化BP网络的初始权重和阈值,提高预测精度。GA通过选择、交叉、变异操作迭代优化,防止局部收敛,增强模型对金融市场复杂性和不确定性的适应能力。
134 80
|
1天前
|
机器学习/深度学习 算法
基于遗传优化的双BP神经网络金融序列预测算法matlab仿真
本项目基于遗传优化的双BP神经网络实现金融序列预测,使用MATLAB2022A进行仿真。算法通过两个初始学习率不同的BP神经网络(e1, e2)协同工作,结合遗传算法优化,提高预测精度。实验展示了三个算法的误差对比结果,验证了该方法的有效性。
|
4天前
|
机器学习/深度学习 数据采集 算法
基于PSO粒子群优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目展示了基于PSO优化的CNN-GRU-SAM网络在时间序列预测中的应用。算法通过卷积层、GRU层、自注意力机制层提取特征,结合粒子群优化提升预测准确性。完整程序运行效果无水印,提供Matlab2022a版本代码,含详细中文注释和操作视频。适用于金融市场、气象预报等领域,有效处理非线性数据,提高预测稳定性和效率。
|
5天前
|
机器学习/深度学习 算法 索引
单目标问题的烟花优化算法求解matlab仿真,对比PSO和GA
本项目使用FW烟花优化算法求解单目标问题,并在MATLAB2022A中实现仿真,对比PSO和GA的性能。核心代码展示了适应度计算、火花生成及位置约束等关键步骤。最终通过收敛曲线对比三种算法的优化效果。烟花优化算法模拟烟花爆炸过程,探索搜索空间,寻找全局最优解,适用于复杂非线性问题。PSO和GA则分别适合快速收敛和大解空间的问题。参数调整和算法特性分析显示了各自的优势与局限。
|
8天前
|
缓存 算法 搜索推荐
Java中的算法优化与复杂度分析
在Java开发中,理解和优化算法的时间复杂度和空间复杂度是提升程序性能的关键。通过合理选择数据结构、避免重复计算、应用分治法等策略,可以显著提高算法效率。在实际开发中,应该根据具体需求和场景,选择合适的优化方法,从而编写出高效、可靠的代码。
23 6
|
14天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
47 3
|
14天前
|
算法
PAI下面的gbdt、xgboost、ps-smart 算法如何优化?
设置gbdt 、xgboost等算法的样本和特征的采样率
34 2
|
29天前
|
算法
基于GA遗传算法的PID控制器参数优化matlab建模与仿真
本项目基于遗传算法(GA)优化PID控制器参数,通过空间状态方程构建控制对象,自定义GA的选择、交叉、变异过程,以提高PID控制性能。与使用通用GA工具箱相比,此方法更灵活、针对性强。MATLAB2022A环境下测试,展示了GA优化前后PID控制效果的显著差异。核心代码实现了遗传算法的迭代优化过程,最终通过适应度函数评估并选择了最优PID参数,显著提升了系统响应速度和稳定性。
128 15
|
26天前
|
算法
基于WOA鲸鱼优化的购售电收益与风险评估算法matlab仿真
本研究提出了一种基于鲸鱼优化算法(WOA)的购售电收益与风险评估算法。通过将售电公司购售电收益风险计算公式作为WOA的目标函数,经过迭代优化计算出最优购电策略。实验结果表明,在迭代次数超过10次后,风险价值收益优化值达到1715.1万元的最大值。WOA还确定了中长期市场、现货市场及可再生能源等不同市场的最优购电量,验证了算法的有效性。核心程序使用MATLAB2022a实现,通过多次迭代优化,实现了售电公司收益最大化和风险最小化的目标。
|
30天前
|
算法
通过matlab分别对比PSO,反向学习PSO,多策略改进反向学习PSO三种优化算法
本项目使用MATLAB2022A版本,对比分析了PSO、反向学习PSO及多策略改进反向学习PSO三种优化算法的性能,主要通过优化收敛曲线进行直观展示。核心代码实现了标准PSO算法流程,加入反向学习机制及多种改进策略,以提升算法跳出局部最优的能力,增强全局搜索效率。

热门文章

最新文章