web-dev-qa-db-ja.com

スタックアルゴリズムを使用した括弧/ブラケットのマッチング

たとえば、かっこ/かっこが以下で一致する場合:

({})
(()){}()
()

等々ですが、括弧/括弧が一致しない場合、falseを返す必要があります。例:

{}
({}(
){})
(()

等々。このコードを確認してください。前もって感謝します。

public static boolean isParenthesisMatch(String str) {
    Stack<Character> stack = new Stack<Character>();

    char c;
    for(int i=0; i < str.length(); i++) {
        c = str.charAt(i);

        if(c == '{')
            return false;

        if(c == '(')
            stack.Push(c);

        if(c == '{') {
            stack.Push(c);
            if(c == '}')
                if(stack.empty())
                    return false;
                else if(stack.peek() == '{')
                    stack.pop();
        }
        else if(c == ')')
            if(stack.empty())
                return false;
            else if(stack.peek() == '(')
                    stack.pop();
                else
                    return false;
        }
        return stack.empty();
}

public static void main(String[] args) {        
    String str = "({})";
    System.out.println(Weekly12.parenthesisOtherMatching(str)); 
}
29
Shuvo0o

コードでは、「{」および「}」文字の処理に多少の混乱があります。 '('および ')'の処理方法と完全に並行する必要があります。

このコードは、あなたのものからわずかに変更されており、適切に動作しているようです:

public static boolean isParenthesisMatch(String str) {
    if (str.charAt(0) == '{')
        return false;

    Stack<Character> stack = new Stack<Character>();

    char c;
    for(int i=0; i < str.length(); i++) {
        c = str.charAt(i);

        if(c == '(')
            stack.Push(c);
        else if(c == '{')
            stack.Push(c);
        else if(c == ')')
            if(stack.empty())
                return false;
            else if(stack.peek() == '(')
                stack.pop();
            else
                return false;
        else if(c == '}')
            if(stack.empty())
                return false;
            else if(stack.peek() == '{')
                stack.pop();
            else
                return false;
    }
    return stack.empty();
}
50
Don Roby

このコードは理解しやすいです:

public static boolean CheckParentesis(String str)
{
    if (str.isEmpty())
        return true;

    Stack<Character> stack = new Stack<Character>();
    for (int i = 0; i < str.length(); i++)
    {
        char current = str.charAt(i);
        if (current == '{' || current == '(' || current == '[')
        {
            stack.Push(current);
        }


        if (current == '}' || current == ')' || current == ']')
        {
            if (stack.isEmpty())
                return false;

            char last = stack.peek();
            if (current == '}' && last == '{' || current == ')' && last == '(' || current == ']' && last == '[')
                stack.pop();
            else 
                return false;
        }

    }

    return stack.isEmpty();
}
40
Rafael Amsili

アルゴリズム:

  1. 文字列をスキャンし、文字列で見つかったすべての「(」をスタックにプッシュします
  2. char ')'がスキャンされた場合、スタックから1つの '('をポップします

現在、括弧は2つの条件でバランスがとられています。

  • '('は、文字列で見つかったすべての ')'のスタックからポップできます。
  • スタックは最後に空です(文字列全体が処理されるとき)
5
Kibrom Gebre
public static boolean isValidExpression(String expression) {
    Map<Character, Character> openClosePair = new HashMap<Character, Character>();
    openClosePair.put(')', '(');
    openClosePair.put('}', '{');
    openClosePair.put(']', '[');        
    Stack<Character> stack = new Stack<Character>();
    for(char ch : expression.toCharArray()) {
        if(openClosePair.containsKey(ch)) {
            if(stack.pop() != openClosePair.get(ch)) {
                return false;
            }
        } else if(openClosePair.values().contains(ch)) {
            stack.Push(ch); 
        }
    }
    return stack.isEmpty();
}

実際には、「手動」でケースをチェックする必要はありません。次のアルゴリズムを実行するだけです。

  1. 指定されたシーケンスを反復処理します。空のスタックから始めます。

  2. 現在の文字が開き括弧の場合は、スタックにプッシュするだけです。

  3. 閉じ括弧の場合は、スタックが空ではなく、ステップの一番上の要素が適切な開き括弧であることを確認します(つまり、これと一致します)。そうでない場合は、エラーを報告してください。それ以外の場合は、スタックから一番上の要素をポップします。

  4. 最後に、スタックが空の場合、シーケンスは正しいです。

なぜ正しいのですか?証明のスケッチは次のとおりです。このアルゴリズムがシーケンスの修正を報告した場合、すべてのブラケットの一致するペアが見つかりました。したがって、シーケンスは定義により実際に正しいです。エラーが報告された場合:

  1. スタックが最後に空ではなかった場合、開き括弧と閉じ括弧のバランスはゼロではありません。したがって、これは正しいシーケンスではありません。

  2. 要素をポップする必要があるときにスタックが空だった場合、バランスは再びオフになります。

  3. スタックの上部に間違った要素があった場合、「間違った」ブラケットのペアは互いに一致するはずです。これは、シーケンスが正しくないことを意味します。

私はそれを示しました:

  • アルゴリズムがシーケンスが正しいと報告した場合、それは正しいです。

  • アルゴリズムがシーケンスが正しくないと報告した場合、それは正しくありません(質問で言及されているケース以外に他のケースがないという事実を使用しないことに注意してください)。

この2つのポイントは、このアルゴリズムがすべての入力に対して機能することを意味しています。

4
kraskevich
public static boolean isBalanced(String s) {
    Map<Character, Character> openClosePair = new HashMap<Character, Character>();
    openClosePair.put('(', ')');
    openClosePair.put('{', '}');
    openClosePair.put('[', ']'); 

    Stack<Character> stack = new Stack<Character>();
    for (int i = 0; i < s.length(); i++) {

        if (openClosePair.containsKey(s.charAt(i))) {
            stack.Push(s.charAt(i));

        } else if ( openClosePair.containsValue(s.charAt(i))) {
            if (stack.isEmpty())
                return false;
            if (openClosePair.get(stack.pop()) != s.charAt(i))
                return false;
        }

        // ignore all other characters

    }
    return stack.isEmpty();
}
1
deniswsrosa

必要のない追加のチェックを行っています。機能の違いはありませんが、コードをより簡潔に記述する方法は次のとおりです。

public static boolean isParenthesisMatch(String str) {
    Stack<Character> stack = new Stack<Character>();
    char c;

    for (int i = 0; i < str.length(); i++) {
        c = str.charAt(i);
        if (c == '(' || c == '{')
            stack.Push(c);
        else if (stack.empty())
            return false;
        else if (c == ')') {
            if (stack.pop() != '(')
                return false;
        } else if (c == '}') {
            if (stack.pop() != '{')
                return false;
        }
    }
    return stack.empty();
}

スタックから削除する前に、括弧を覗く理由はありません。また、読みやすさを向上させるために、命令ブロックを括弧で囲むことも検討します。

1
tfp95

上記のGanesanの答えは正しくなく、StackOverflowは私に彼の投稿へのコメントや編集を許可していません。以下が正しい答えです。 Ganesanには間違った向きの「[」があり、スタックのisEmpty()チェックがありません。

以下のコードは、中括弧が適切に一致する場合にtrueを返します。

public static boolean isValidExpression(String expression) {
    Map<Character, Character> openClosePair = new HashMap<Character, Character>();
    openClosePair.put(')', '(');
    openClosePair.put('}', '{');
    openClosePair.put(']', '[');

    Stack<Character> stack = new Stack<Character>();
    for(char ch : expression.toCharArray()) {
        if(openClosePair.containsKey(ch)) {
            if(stack.isEmpty() || stack.pop() != openClosePair.get(ch)) {
                return false;
            }
        } else if(openClosePair.values().contains(ch)) {
            stack.Push(ch); 
        }
    }
    return stack.isEmpty();
}
1
Jared

StacksおよびSwitchステートメントを使用した実装の最適化:

public class JavaStack {

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

      Stack<Character> s = new Stack<Character>();

    while (sc.hasNext()) {
        String input = sc.next();

        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            switch (c) {

                case '(':
                    s.Push(c); break;
                case '[':
                    s.Push(c); break;
                case '{':
                    s.Push(c); break;
                case ')':
                    if (!s.isEmpty() && s.peek().equals('(')) {
                        s.pop();
                    } else {
                        s.Push(c);
                    } break;
                case ']':
                    if (!s.isEmpty() && s.peek().equals('[')) {
                        s.pop();
                    } else {
                        s.Push(c);
                    } break;
                case '}':
                    if (!s.isEmpty() && s.peek().equals('{')) {
                        s.pop();
                    } else {
                        s.Push(c);
                    } break;

                default:
                    s.Push('x'); break;

            }

        }
        if (s.empty()) {
            System.out.println("true");
        } else {
            System.out.println("false");
            s.clear();
        }
    }
} }

乾杯!

1
Leo

アルゴリズムは:

1)Create a stack

2)while(end of input is not reached)

   i)if the character read is not a sysmbol to be balanced ,ignore it.

   ii)if the character is {,[,( then Push it to stack

   iii)If it is a },),] then if 

        a)the stack is empty report an error(catch it) i.e not balanced

        b)else pop the stack 

   iv)if element popped is not corresponding to opening sysmbol,then report error.

3) In the end,if stack is not empty report error else expression is balanced.  

Javaコード

public class StackDemo {
    public static void main(String[] args) throws Exception {
        System.out.println("--Bracket checker--");
        CharStackArray stack = new CharStackArray(10);
        stack.balanceSymbol("[a+b{c+(e-f[p-q])}]") ;
        stack.display();

    }

}    

class CharStackArray {
        private char[] array;
        private int top;
        private int capacity;

        public CharStackArray(int cap) {
            capacity = cap;
            array = new char[capacity];
            top = -1;
        }

        public void Push(char data) {
            array[++top] = data;
        }

        public char pop() {
            return array[top--];
        }

        public void display() {
            for (int i = 0; i <= top; i++) {
                System.out.print(array[i] + "->");
            }
        }

        public char peek() throws Exception {
            return array[top];
        }

        /*Call this method by passing a string expression*/
        public void balanceSymbol(String str) {
            try {
                char[] arr = str.toCharArray();
                for (int i = 0; i < arr.length; i++) {
                    if (arr[i] == '[' || arr[i] == '{' || arr[i] == '(')
                        Push(arr[i]);
                    else if (arr[i] == '}' && peek() == '{')
                        pop();
                    else if (arr[i] == ']' && peek() == '[')
                        pop();
                    else if (arr[i] == ')' && peek() == '(')
                        pop();
                }
                if (isEmpty()) {
                    System.out.println("String is balanced");
                } else {
                    System.out.println("String is not balanced");
                }
            } catch (Exception e) {
                System.out.println("String not balanced");
            }

        }

        public boolean isEmpty() {
            return (top == -1);
        }
    }

出力:

-ブラケットチェッカー-

弦のバランスが取れている

1
Prateek Joshi
import Java.util.*;

class StackDemo {

    public static void main(String[] argh) {
        boolean flag = true;
        String str = "(()){}()";
        int l = str.length();
        flag = true;
        Stack<String> st = new Stack<String>();
        for (int i = 0; i < l; i++) {
            String test = str.substring(i, i + 1);
            if (test.equals("(")) {
                st.Push(test);
            } else if (test.equals("{")) {
                st.Push(test);
            } else if (test.equals("[")) {
                st.Push(test);
            } else if (test.equals(")")) {
                if (st.empty()) {
                    flag = false;
                    break;
                }
                if (st.peek().equals("(")) {
                    st.pop();
                } else {
                    flag = false;
                    break;
                }
            } else if (test.equals("}")) {
                if (st.empty()) {
                    flag = false;
                    break;
                }
                if (st.peek().equals("{")) {
                    st.pop();
                } else {
                    flag = false;
                    break;
                }
            } else if (test.equals("]")) {
                if (st.empty()) {
                    flag = false;
                    break;
                }
                if (st.peek().equals("[")) {
                    st.pop();
                } else {
                    flag = false;
                    break;
                }
            }
        }
        if (flag && st.empty())
            System.out.println("true");
        else
            System.out.println("false");
    }
}
0
Ashish Jadhav

私はここで答えを見ましたが、ほとんどすべてがうまくいきました。ただし、検出されたブレースの順序を監視するために、ブラケットペアとスタックを管理するための辞書を使用する独自のバージョンを作成しました。私もブログを書いています post このため。

これが私のクラスです

public class FormulaValidator
{
    // Question: Check if a string is balanced. Every opening bracket is matched by a closing bracket in a correct position.
    // { [ ( } ] )

    // Example: "()" is balanced
    // Example: "{ ]" is not balanced.
    // Examples: "()[]{}" is balanced.
    // "{([])}" is balanced
    // "{ ( [ ) ] }" is _not_ balanced

    // Input: string, containing the bracket symbols only
    // Output: true or false
    public bool IsBalanced(string input)
    {
        var brackets = BuildBracketMap();
        var openingBraces = new Stack<char>();
        var inputCharacters = input.ToCharArray();

        foreach (char character in inputCharacters)
        {
            if (brackets.ContainsKey(character))
            {
                openingBraces.Push(character);
            }

            if (brackets.ContainsValue(character))
            {
                var closingBracket = character;
                var openingBracket = brackets.FirstOrDefault(x => x.Value == closingBracket).Key;

                if (openingBraces.Peek() == openingBracket)
                    openingBraces.Pop();
                else
                    return false;
            }
        }

        return openingBraces.Count == 0;
    }

    private Dictionary<char, char> BuildBracketMap()
    {
        return new Dictionary<char, char>()
        {
            {'[', ']'},
            {'(', ')'},
            {'{', '}'}
        };
    }
}
0
Allan Chua

私は最高の答えだと思います:

public boolean isValid(String s) {
    Map<Character, Character> map = new HashMap<>();
    map.put('(', ')');
    map.put('[', ']');
    map.put('{', '}');
    Stack<Character> stack = new Stack<>();
    for(char c : s.toCharArray()){
        if(map.containsKey(c)){
            stack.Push(c);
        } else if(!stack.empty() && map.get(stack.peek())==c){
            stack.pop();
        } else {
            return false;
        }
    }
    return stack.empty();
}
0
Max.Futerman