• LeetCode刷题笔记第20题(括号匹配)


    题目:

    括号匹配,就是给定的字符串中,只有"{ 、}、 [、 ] (、)"这几种字符,其中有效字符串需满足:

    1. 左括号必须用相同类型的右括号闭合。
    2. 左括号必须以正确的顺序闭合。
    3. 空字符串也是有效字符串。

    分析:

    这个题目最早接触是在大学本科课程数据结构中接触到的,而它正是栈的一种应用,所以可以借助于栈来解决。

    首先第一种比较通用的解法,借助栈,主要算法思想是:

      1.遍历字符串;

      2.如果遇到的字符属于左括号范畴则入栈;

      3.如果碰到的是右括号范畴,则有以下三种情况

        (1)如果此时栈为空,说明没有与之匹配的左括号,所以不是有效串;

        (2)如果此时的这个右括号与栈的栈顶元素不匹配,说明不是有效串;

        (3)如果此时这个右括号与栈顶元素匹配了,则继续向下运行

    实现的代码如下:

        public boolean isValid(String s) {
            if (s.length() == 0)
                return true;
            if (s.length() == 1)
                return false;
            Stack<Character> stack = new Stack<>();
            char[] chars = s.toCharArray();
            for (char aChar : chars) {
                if (aChar == '(' || aChar == '[' || aChar == '{')
                    stack.push(aChar);
                if (stack.isEmpty() && (aChar == ')'||aChar=='}'||aChar==']'))
                    return false;
                if ((aChar == ')'||aChar=='}'||aChar==']')){
                    char temp = stack.pop();
                    switch (aChar){
                        case ')' :
                            if (temp != '(')
                                return false;
                            break;
                        case '}':
                            if (temp != '{')
                                return false;
                            break;
                        case ']':
                            if (temp != '[')
                                return false;
                            break;
                    }
                }
            }
            if (stack.isEmpty())
                return true;
            else
                return false;
        }

    其实还可以对上面的程序进行优化,首先分析题目,一个有效串其长度必然是2的倍数,所以对2进行取模运算一定为0,通过这个方法我们可以快速的过滤掉许多字符串长度为奇数的串,因为它们肯定不是有效串。通过对以上的代码进行简化,如下所示:

        public boolean isValid(String s) {
    
            if (s.length() % 2 !=0)
                return false;
            if (s.length() == 0)
                return true;
    
            Stack<Character> stack = new Stack<>();
    
            for (int i = 0;i < s.length();i ++){
                char c = s.charAt(i);
    
                switch (c){
                    case '{':
                    case '[':
                    case '(':
                        stack.push(c);
                        break;
                    case '}':
                    case ')':
                    case ']': {
                        if (!stack.empty()){
                            char left_c = stack.pop();
                            if ((c=='}'&&left_c!='{')||(c==')'&&left_c!='(')||(c==']'&&left_c!='['))
                                return false;
                        }
                    }
                }
            }
            return stack.empty();
        }

    一定要注意switch语句的注意使用,其中case语句下如果没有break,那么程序会顺着向下执行其他case语句中的程序。

    第二种解法,也是栈的思想,但是并没有使用真正的栈,而是借用一个字符数组模拟栈来使用,出栈与进栈都是通过索引值的变化来实现的,代码如下:

        public boolean isValid_2(String s) {
            char[] chs = new char[s.length()];
            int index = 0;
            for(char c : s.toCharArray()){
                if( c != ')' && c != '}' && c != ']' ){
                    chs[index++] = c;
                }else if(index == 0){
                    return false;
                }else if( c == ')' && chs[index-1] == '('){
                    index--;
                }else if( c == '}' && chs[index-1] == '{'){
                    index--;
                }else if( c == ']' && chs[index-1] == '['){
                    index--;
                }else{
                    return false;
                }
            }
            return index == 0;
        }

    第三种解法,则利用了一些比较高级的特性,即通过哈系表(HashMap)和集合(List),首先以左括号为key、右括号为value的形式存入三种括号,然后以"?"代替空字符串的含义。具体过程如下:

      1.预先判断字符串是否大于0同时第一个字符是否为map中的key,即是否属于左括号,如果不是则返回false;

      2.初始化一个链表作为栈,因为该程序插入和删除多,所以使用LinkedList更快,先存入一个值"?";

      3.逐个遍历要字符串中的每个字符,然后判断当前字符是否属于map中的key,如果属于则加入集合

      4.第三步的字符如果不属于map中的key,即不是左括号同时也不是"?",则将list集合的最后一个元素取出(相当于栈顶元素)作为map的key以此来提取出对应的value

      5.比较value和当前字符是否相同,如果不同则返回false,否则程序继续运行。

       6.最后集合中如果元素个数为1,则说明是有效串,否则返回false。

    综合来看,还是相当于借助了栈的思想,感觉这个程序做法很独特,但是又显得多次一举,因为明明简单的if结构就能完成,非得用点哈希表等结构,不过这也帮助我们拓宽了解题的思维。代码如下:

        private static final Map<Character,Character> map = new HashMap<Character,Character>(){{
            put('{','}'); put('[',']'); put('(',')'); put('?','?');
        }};
        public boolean isValid3(String s) {
            if(s.length() > 0 && !map.containsKey(s.charAt(0))) return false;
            LinkedList<Character> stack = new LinkedList<Character>() {{ add('?'); }};
            for(Character c : s.toCharArray()){
                if(map.containsKey(c)) stack.addLast(c);
                else if(map.get(stack.removeLast()) != c) return false;
            }
            return stack.size() == 1;
        }
    
        public static void main(String[] args){
            Tip020 t = new Tip020();
            String s = "";
    
            if (t.isValid_2(s))
                System.out.println(s+"  匹配成功!");
            else
                System.out.println("匹配失败");
        }
  • 相关阅读:
    HDU 3709 Balanced Number
    HDU 3652 B-number
    HDU 3555 Bomb
    全局和局部内存管理
    [转]
    [转]
    [转]
    The Stable Marriage Problem
    STL各种容器的使用时机详解
    Qt中图像的显示与基本操作
  • 原文地址:https://www.cnblogs.com/yxym2016/p/12563401.html
Copyright © 2020-2023  润新知