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("匹配失敗");
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM