java判断有效的括号序列

需求:

给定一个字符串所表示的括号序列,包含以下字符: '(', ')', '{', '}','[' and']', 判定是否是有效的括号序列。

分析:

1、对于有效的括号序列,满足下列特点:

    1)有效的括号序列长度是不为0的偶数,所以字符串长度为0或者奇数时就返回false

    2)如果第一个字符是右括号或者最后一个字符是左括号,那么不是有效括号序列,会返回false

    上述1)和2)可以直接判断不是有效括号序列,这样就减少了内存以及时间开销。比如对于"{(){"序列,如果不进行2)的判断,可能需要开辟堆栈空间,判断到最后才得出false的结论,但是如果一开始就判断开头和结尾是否满足有效括号序列的条件,就可以不开辟堆栈空间,进而减少内存开销,提高代码效率。

2、数据结构选用堆栈

    堆栈是一种LIFO(后进先出)的数据结构。遍历字符串,将左括号推入堆栈,对于右括号,判断栈顶元素与其是否匹配,如果不匹配就不有效,否则弹出栈顶元素,说明该层的括号已经判断完毕,继续遍历字符串进行判断。遍历之后,需要判断堆栈是否为空,如果不是空的,说明左括号多于右括号,不有效,返回false,否则返回true。

3、java中的堆栈实现

   1) Stack类

    JDK1.0提供了Stack类,即堆栈类,有如下方法

    boolean empty()//判断堆栈是否为空
    E push(E e)//将元素e推入栈顶
    E peek()//获取栈顶元素
    E pop()//弹出栈顶元素
    int search(Object obj)//此方法返回距堆栈顶部最近的出现位置到堆栈顶部的距离;堆栈中最顶部项的距离为 1。使用equals 方法比较o 与堆栈中的项。

    2)Deque接口

    Deque(Double ended queue双端队列)接口实现了提供LIFO堆栈操作的一系列更完整和更一致的set,应该优先使用Deque的子类,而非Stack,比如:

    Deque<Integer> deq = new ArrayDeque<Integer>();

    在将双端队列用作队列时,将得到 FIFO(先进先出)行为。将元素添加到双端队列的末尾,从双端队列的开头移除元素。从Queue接口继承的方法完全等效于Deque方法;双端队列也可用作 LIFO(后进先出)堆栈。应优先使用此接口而不是遗留Stack 类。在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。堆栈方法完全等效于Deque方法。

    ArrayDeque是Deque的子类,既可以实现堆栈,又可以实现队列。ArrayDeque用作堆栈时,效率比Stack高,用作队列时,效率比LinkedList高,所以一般使用ArrayDeque来实现堆栈和队列的数据结构。

    3)Deque接口方法摘要

    a)判断

    boolean isEmpty()//判断是否是空的

    b)添加元素

    void push(E e)//将元素e推入表示的堆栈栈顶
    boolean offer(E e)//在双端队列尾部添加元素等价于offerLast()
    boolean offerFirst(E e)//在双端队列头部添加元素
    boolean offerLast(E e)//在双端队列尾部添加元素
    使用offer替换add方法

    c)获取元素

    E peek()//获取双端队列头部元素,等价于peekFirst()
    E peekFirst()//获取双端队列头部元素
    E peekLast()//获取双端队列尾部元素
    使用peek替换get方法

    d)删除元素

    E pop()//弹出栈顶元素
    E poll()//获取并移除队列头部元素,等价于pollFirst()
    E pollFirst()
    E pollLast()//获取并移除双端队列尾部元素
    使用poll代替remove

    e)获取元素个数

    int size()

    4)ArrayDeque

    用作堆栈:push(E e)                    pop()    peek()/peekFirst()
    用作队列:offer(E e)/offerLast(E e)    poll()   peek()

步骤:

1、判断分析中的1)和2)条件,提高代码效率。如果返回false,程序结束,否则进行步骤2

2、创建堆栈,遍历字符串,如果是左括号,则推入堆栈中,如果是右括号,判断堆栈是否是空的,如果是空的返回false,否则看栈顶元素是否和该右括号匹配,如果不匹配返回fasle,如果匹配就将栈顶弹出,继续遍历字符串

3、字符串遍历结束,判断堆栈是否是空的,如果不是空的,说明左括号数量大于右括号,不是有效括号序列,返回false,否则返回true

代码:

public class Solution {
    /*
     * @param s: A string
     * @return: whether the string is a valid parentheses
     */
    public boolean isValidParentheses(String s) {
        // write your code here
        //如果字符串为null或者长度是奇数或者0,那么就不是有效括号,就返回false
        //如果字符串的头部是右括号或者尾部是左括号,返回fasle
        int len = s.length();
        if(s == null || len == 0 || len % 2 != 0)
        {
            return false;
        }
        
        char start = s.charAt(0);
        char end = s.charAt(len - 1);
        if(start == '}' || start == ')' || start == ']')
        {
            return false;
        }
        if(end == '{' || end == '(' || end == '[')
        {
            return false;
        }
        
        //创建堆栈
        Deque<Character> stack = new ArrayDeque<Character>();
        
        //遍历字符串,如果是左括号就添加到堆栈中,如果是右括号,看是否和栈顶元素匹配,匹配就pop栈顶元素,不匹配就返回false,如果遍历到最后一个元素,并且和栈顶元素匹配即可返回true,否则fasle
        for(int i = 0; i < len; i++)
        {
            char ch = s.charAt(i);
            
            //如果是左括号就直接添加进堆栈
            if(ch == '{' || ch == '(' || ch == '[')
            {
                stack.push(ch);
            }
            //如果是右括号,进行匹配判断
            else if(ch == '}' || ch ==')' || ch ==']')
            {
                if(stack.isEmpty())
                {
                    return false;
                }
                else
                {
                    char peek = stack.peek();
                    if(isMatch(peek, ch))
                    {
                        stack.pop();
                    }
                    else
                    {
                        return false;
                    }
                }
            }
        }
        
        //判断堆栈是否是空的,如果是空的,就是
        if(stack.isEmpty())
        {
            return true;
        }
        
        return false;
    }
    
    //判断是否是匹配的括号对
    public boolean isMatch(char c1, char c2)
    {
        return (c1 == '{' && c2 == '}' || c1 == '(' && c2 == ')' || c1 == '[' && c2 == ']')? true: false;
    }

}



  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值