括号匹配那个小题真不简单……

简介: 括号匹配那个小题真不简单……

括号匹配那个小题真不简单……

这是一个括号匹配的小问题引发的思考,很多题目很简单,很多刚接触编程的人都可以做出来。

但是一道算法题不是解出来就完事了,更多的要去探索不同的解法,分析每种解法的不同之处,尝试找出来最优的那种解法。不如你也来试试看。

先来看看这个小题目,简单的来说就是括号匹配的最基础版本。

Description:

有这样一个数学表达式:((2+3)*(4+5))判断它的左右括号是否匹配。如果匹配正确输出括号的对数,否则输出-1。

Example :

Input:((2+3)*(4+5))
Output:3

Tips:

括号匹配这种题,里面需要操作的符号有两种:左括号和右括号,那么我们就可以针对这两个符号操作,其余的数字字符都可以忽略掉。

这里有一些要考虑的特殊情况,比如表达式没有括号的存在,这时候该怎么办呢?

学过栈的同学可以使用栈的操作把这一题给解答了,那么除此以外,不使用栈的情况下,是不是还有其他解法呢?

Solutions:

我们先来看看第一种解法,使用栈操作,只需要一个栈就可以了,此时遇到右括号进栈,遇到左括号则出栈,这时候栈中的右括号少一个,计数变量 +1 操作。最后判断栈是否为空?为空则表示括号匹配,输出计数变量的值,否则输出 -1。

代码实现如下所示:

import java.util.Scanner;
import java.util.Stack;
/**
 * 使用栈解法,此处有遗留问题
 */
public class Solution01 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        int count = 0;
        int len = str.length() - 1;
        Stack stack = new Stack<String>();
        while (len >= 0) {
            char c = str.charAt(len);
            if (c == ')') {
                stack.push(c);
            } else if (c == '(') {
                stack.pop();
                ++count;
            }
            --len;
        }
        if (stack.isEmpty()) {
            System.out.println(count);
        } else {
            System.out.println(-1);
        }
    }
}

你是不是以为这样就结束了?哦不……还有两个问题,假如在出栈的时候,栈为空,这里会抛异常的,这该怎么搞呢?如果( 的数量比 ) 的数量少,那又会怎么样

那么就接下来分析一下栈解法的时间复杂度和空间复杂度,其中包含一个循环操作,循环的次数跟字符串的长度相同,那么我们使用大O表示法,那么此时的时间复杂度可以记做O(n)

然后我们分析一下空间复杂度,这里额外使用的空间最多的就是开辟的栈空间,这里的栈空间可大可小,最小的时候可以为空,最大的时候需要空间就是字符串的长度,即为n,平均空间复杂度的分析可以使用我们上次的内容进行分析,忽略系数的情况下,可以记为O(n)

然后我们来看看第二种解法,我们是不是可以把栈替换掉呢?比如使用变量计数,使用两个变量分别记录左右括号的数量,如果最后数量相同则输出统计的数量,否则输出-1。

代码实现如下所示:

import java.util.Scanner;
public class Solution02 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        int i = str.length() - 1;
        int left = 0;
        int right = 0;
        while (i >= 0) {
            char c = str.charAt(i);
            if (c == ')') {
                ++right;
            } else if (c == '(') {
                ++left;
            }
            --i;
        }
        if (left == right) {
            System.out.println(left);
        } else {
            System.out.println(-1);
        }
    }
}

我们来分析这段代码,同样的循环操作,循环的次数跟字符串的长度相同,那么我们使用大O表示法,这里的时间复杂度也可以记做O(n)

然后我们分析一下空间复杂度,这里额外使用的空间就是两个计数的变量,这两个变量不会随着字符串规模的增长而需要更多的空间,所以这里的空间复杂度是常量级别的,可以记做O(1)


你以为这就结束了?不可能的,这还不是最优的,还有一种解法,比较有意思,我只提供一下思路,有兴趣的可以去试试。

首先剔除掉字符串中的非括号字符,然后判断字符串中包含()的数量。匹配一对删除一对,在最后的时候,判断字符串的长度是否为0,是的话就输出数量,不是的话,就是-1咯。

代码实现可以参考下图,有兴趣的建议自己实现一下。

image.png

最后来一个问题,那么它的时间复杂度和空间复杂度是多少呢?

目录
相关文章
|
4月前
|
C++
【洛谷 P1739】表达式括号匹配 题解(栈)
该编程题目要求检查给定的包含字母、运算符和括号的表达式是否括号匹配。输入为一行表达式,以`@`结束。如果括号匹配,输出`YES`,否则输出`NO`。样例包括一个匹配和一个不匹配的表达式。解决方案是使用栈,遇到左括号入栈,遇到右括号时判断栈是否为空,栈空则输出`NO`,否则出栈。当读到`@`时,栈空则输出`YES`,否则输出`NO`。提供的AC代码使用C++实现,通过`stack`处理括号匹配。
44 0
|
5月前
牛客数对题目详解
牛客数对题目详解
26 0
|
11月前
|
存储 算法 C语言
【C语言刷题】猜名次、猜凶手、杨辉三角、杨氏矩阵、字符串左旋、判断是否为左旋子串
【C语言刷题】猜名次、猜凶手、杨辉三角、杨氏矩阵、字符串左旋、判断是否为左旋子串
70 0
每日刷题|回溯法解决全排列问题第二弹之解决字符串、字母大小排列问题
每日刷题|回溯法解决全排列问题第二弹之解决字符串、字母大小排列问题
杨氏矩阵,字符串左旋,字符串旋转结果题目解析
杨氏矩阵,字符串左旋,字符串旋转结果题目解析
|
机器学习/深度学习 算法 NoSQL
【基础算法】浅浅刷个小题 # 反转字符串 # 反转字符串 II # 三个数的最大乘积 #
【基础算法】浅浅刷个小题 # 反转字符串 # 反转字符串 II # 三个数的最大乘积 #
卡特兰数—以leetcode22括号生成为例(笔记)
卡特兰数—以leetcode22括号生成为例(笔记)
|
测试技术
每日一题——倒置字符串
将一句话的单词进行倒置,标点不倒置。比如 I like beijing. 经过函数后变为:beijing. like I
101 0
【括号匹配&洛谷&进制转换】栈的实战,包教包会
【括号匹配&洛谷&进制转换】栈的实战,包教包会
79 0
【括号匹配&洛谷&进制转换】栈的实战,包教包会