检查字符串具有平衡括号

时间:2009-09-04 17:38:56

标签: c# algorithm

我正在阅读算法设计手册第二版,这是一个练习题。引用问题

  

编译器和编译器的常见问题   文本编辑正在决定是否   字符串中的括号是   平衡和适当嵌套。对于   例如,字符串((())())()   包含正确嵌套的对   括号,其中的字符串)()(   也不要。给出一个算法   如果字符串包含,则返回true   适当嵌套和平衡   括号,否则为假。   要获得全额信贷,请确定头寸   如果是第一个违规括号   字符串没有正确嵌套   平衡的。

问题在堆栈,队列和列表类别下。这是我在C#中写的内容。

const char LeftParenthesis = '(';
const char RightParenthesis = ')';
bool AreParenthesesBalanced(string str, out int errorAt)
{
    var items = new Stack<int>(str.Length);
    errorAt = -1;
    for (int i = 0; i < str.Length; i++)
    {
        char c = str[i];
        if (c == LeftParenthesis)
            items.Push(i);
        else if (c == RightParenthesis)
        {
            if (items.Count == 0)
            {
                errorAt = i + 1;
                return false;
            }
            items.Pop();
        }
    }
    if (items.Count > 0)
    {
        errorAt = items.Peek() + 1;
        return false;
    }
    return true;
}

这很有效。但我不确定这是解决这个问题的正确方法。欢迎任何更好的想法。

18 个答案:

答案 0 :(得分:10)

我认为这是意图,但实际上,如果你只处理括号,你只需要递减和增加一个计数器。如果你正在处理方括号,尖括号,花括号或你想要使用的任何字符配对的配对,你将需要像你一样的堆栈。

你也可以使用一个列表,关闭和打开head元素,但实际上堆栈可能实现为列表 - 至少它是在ocaml中。

答案 1 :(得分:8)

    static public bool CheckForBalancedBracketing(string IncomingString)
    {
    /*******************************************************************
     * The easiest way to check for balanced bracketing is to start    *
     * counting left to right adding one for each opening bracket, '(' *
     * and subtracting 1 for every closing bracket, ')'.  At the end   *
     * the sum total should be zero and at no time should the count    *
     * fall below zero.                                                *
     *                                                                 *
     * Implementation:  The bracket counting variable is an unsigned   *
     * integer and we trap an overflow exception.  This happens if the *
     * unsigned variable ever goes negative.  This allows us to abort  *
     * at the very first imbalance rather than wasting time checking   *
     * the rest of the characters in the string.                       *
     *                                                                 *
     * At the end all we have to do is check to see if the count       *
     * is equal to zero for a "balanced" result.                       *
     *                                                                 *
     *******************************************************************/
        const char LeftParenthesis = '(';
        const char RightParenthesis = ')';
        uint BracketCount = 0;

        try
        {
            checked  // Turns on overflow checking.
            {
                for (int Index = 0; Index < IncomingString.Length; Index++)
                {
                    switch (IncomingString[Index])
                    {
                        case LeftParenthesis:
                            BracketCount++;
                            continue;
                        case RightParenthesis:
                            BracketCount--;
                            continue;
                        default:
                            continue;
                    }  // end of switch()

                }
            }
        }

        catch (OverflowException)
        {
            return false;
        }

        if (BracketCount == 0)
        {
            return true;
        }

        return false;

    }  // end of CheckForBalancedBracketing()

答案 2 :(得分:2)

  1. 从输入字符串中删除所有非'('和 - ')'字符。这只会给你一串'('和')'。

  2. 如果字符串的长度为奇数,则返回false。

  3. 否则,请开始阅读我们的字符串,为每个'('和-1代表')'的“签名”添加+1;如果此签名为负数,则返回false。

  4. 返回true。

答案 3 :(得分:2)

这将适用于(){}[]的组合。

还检测到以下错误:([)])[]()()(,...

bool isWellFormatted(string line)
{           
        Stack<char> lastOpen = new Stack<char>();
        foreach (var c in line)
        {               
            switch (c)
            {
                case ')':
                    if (lastOpen.Count == 0 || lastOpen.Pop() != '(') return false;
                    break;
                case ']':
                    if (lastOpen.Count == 0 || lastOpen.Pop() != '[' ) return false;
                    break;
                case '}':
                    if (lastOpen.Count == 0 || lastOpen.Pop() != '{') return false;
                    break;
                case '(': lastOpen.Push(c); break;
                case '[': lastOpen.Push(c); break;
                case '{': lastOpen.Push(c); break;
            }                                                                       
        }
        if (lastOpen.Count == 0) return true;
        else return false;
    }

答案 4 :(得分:1)

using System;
class Solution
{
    public int solution(string S)
    {
        int x1 = 0;
        int x2 = 0;
        for (int i = 0; i < S.Length; i++)
        {
            if (S[i] == ')')
                if (x1 <= 0) return 0;
                else x1--;
            else if (S[i] == '(')
                x1++;
        }
        if (x1 == 0)
            return 1;
        else
            return 0;
    }
}

答案 5 :(得分:1)

时间顺序O(n)和空间顺序O(1)

public static bool IsBalanced(string input)
{
   int count = 0;
   for (int i = 0; i < input.Length; i++)
   {
       if (input[i] == '(') count++;
       if (input[i] == ')') count--;
       if (count < 0) return false;
    }
    if (count == 0) return true;
    return false;
}

来自http://yadiragarnicabonome.com/parentheses-algorithms/

答案 6 :(得分:0)

C#7左右现在也有元组。您不再需要out参数。 正如许多其他人指出的那样,不需要堆栈,队列或类似内容。
只需一个余额计数器即可。

    -- Checks the balance of braces in a string.
    -- Error case 1: More closes than open. We can identify the first culprit by index.
    -- Error case 2: More opens than closes. We return the length of the String, 
    --               indicating that there are closed braces missing.
    -- Good case: As many opens as closes. We return (True,Nothing)
    checkBraces :: String -> (Bool,Maybe Int)
    checkBraces [] = (True,Nothing)
    checkBraces s =
        let (balance,offender) = foldl account (0,-1) $ zip [0..] s in
        if balance == 0 
            then (True,Nothing) 
            else (False,Just $ if -1 == offender then length s else offender)
        where
            account :: (Int,Int) -> (Int, Char) -> (Int,Int)
            account acc@(_,off) _ | off /= -1 = acc     -- Once there was an error we stop looking what happens.
            account acc@(b,off) (i,'(') = (b+1,off)     -- One more open brace.
            account (b,off) (i,')')                     -- One more closed brace.
                    | b <= 0 = (b-1,i)                  -- Ouch. We closed more than we opened!
                    | otherwise = (b-1,off)             -- Okay.
            account acc (i,_) = acc                     -- Some other character (Not in ['(',')'])


    testCases =
        [ ("",True)
        , ("(",False)
        , (")",False)
        , ("))((",False)
        , ("()()",True)
        , ("(()))",False)
        ]

    test = 
        all ((==) True) . fmap testOne $ testCases
        where
            testOne (tc,expected) =
                let (actual,_) = checkBraces tc in
                actual == expected

旁注:这里Haskell的语法突出显示需要改进,对吗? :)

答案 7 :(得分:0)

我使它更通用 Java

public static boolean isBalanced(String expression)
{
    // pairs at the same index
    List<Character> openers = Arrays.asList('{', '(', '[');
    List<Character> closers = Arrays.asList('}', ')', ']');
    char[] exp = expression.toCharArray();
    Stack<Character> stack = new Stack<>();
    for(Character character: exp){
        if (openers.contains(character))
            stack.push(character);
        if(closers.contains(character)){
            if (stack.empty())
                return false;
            //matching pair should be at the same index
            Character opener = stack.pop();
            int openerIndex = openers.indexOf(opener);
            int closerIndex = closers.indexOf(character);
            if (openerIndex != closerIndex)
                return false;
        }
    }
    return stack.empty();
}

答案 8 :(得分:0)

我将使用队列和堆栈来检查开始和结束比赛

        var dictionary = new Dictionary<string, string>() {
            { "{", "}" },
            {"[", "]" },
            {"(",")" }
        };


        var par = "{()}";
        var queue = new Queue();
        var stack = new Stack();

        bool isBalanced = true;

        var size = par.ToCharArray().Length;

        if(size % 2 != 0)
        {
            isBalanced = false;
        }
        else
        {
            foreach (var c in par.ToCharArray())
            {
                stack.Push(c.ToString());
                queue.Enqueue(c.ToString());
            }

            while (stack.Count > size/2 && queue.Count > size/2)
            {
                var a = (string)queue.Dequeue();
                var b = (string)stack.Pop();

                if (dictionary.ContainsKey(a) && b != dictionary[a])
                {
                    isBalanced = false;

                }


            }


        }

        Console.WriteLine(isBalanced?"balanced!":"Not Balanced");

        Console.ReadLine();

例如在第一次迭代中,a ='{'和b ='}',因此您要检查它是否平衡

答案 9 :(得分:0)

这应该有效:

public class Balanced {
    public static boolean isbalanced(String input) {
        int open = 0;
        int close = 0;
        for (int i=0; i< input.length();i++) {
            switch (input.charAt(i)) {
                case '{':
                case '(':
                case '[':
                    open++;
                    break;
                case '}':
                case ')':
                case ']':
                    close++;
            default:
                break;
            }
        }
        if (open == close){
            return true;
        }
        else {
            return false;
        }
    }

public static void main(String args[]) {
    System.out.println(Balanced.isbalanced("()"));
}
}

答案 10 :(得分:0)

这里是使用System.Linq的C#单行:

expression.Aggregate(0, (state, ch) => state == -1 ? -1 : state + (ch == '(' ? 1 : ch == ')' ? -1 : 0)) == 0

它利用了字符串实际上是IE数量的字符这一事实,因此我们可以在其上运行聚合函数。当我们遇到&#39;(&#39; char并将其减少1&#39;)时,我们将计数器增加1。焦炭。一旦我们达到负值-1,我们就会留在那里表明无效状态。

它没有实现任何早期退出,所以它会比这里介绍的大多数实现慢,但也许有人会发现它很有用:)

答案 11 :(得分:0)

回想@Russell的想法:

public class BalancedBrackets
{
    private readonly char[] _leftBrackets = new char[] {'[', '(', '{', '<'};
    private readonly char[] _rightBrackets = new char[] {']', ')', '}', '>'};

    public bool IsBalanced(string input)
    {
        int count = 0;
        foreach (var character in input.ToCharArray())
        {
            if (_leftBrackets.Contains(character)) count++;
            if (_rightBrackets.Contains(character)) count--;
        }
        return count == 0;
    }
}

答案 12 :(得分:0)

以下是验证括号的简单解决方案:
1.将起始括号和结束括号保持在一个字符串中 2.循环给我们要验证的人,并检查以下逻辑:

a)如果项目在起始括号中,则将其推入堆叠中 b)如果项目在结束括号中,则将其索引(在结束括号中)与堆栈的顶部项目进行比较 index(在起始括号中)。
c)如果索引是相同的POP TOP ITEM OF STACK。否则它的无效字符串。
d)最后一步,检查堆栈是否有项目/ s,表示无效字符串。

    string starters = "({[<";
    string enders = ")}]>";
    Stack stack  = new Stack();
    foreach(char c in txtValue.Text.Trim())
    {
        if(starters.Contains(c))
        {
            stack.Push(c);
        }
        else if (enders.Contains(c))
        {
            if (stack.Count > 0)
            {

                if (enders.IndexOf(c) == starters.IndexOf(Convert.ToChar(stack.Peek())))
                {
                    stack.Pop();
                }
                else
                {
                    lblResult.Text = "Invaluid string";
                }
            }
        }
    }

    if(stack.Count == 0)
    {
        lblResult.Text = "Valid string";
    }
    else
    {
        lblResult.Text = "InValid string";
    }

答案 13 :(得分:0)

import java.util.Stack;

public class CheckBalancedParenthesis {

    public static void main (String args[]){
        CheckBalancedParenthesis checker = new CheckBalancedParenthesis();
        System.out.println(checker.checkBalancedParenthesis("{}}{}{}{}{}"));
    }

    public boolean checkBalancedParenthesis(String pattern){
        Stack stack = new Stack();
        for(int i = 0; i < pattern.length();i++){
            char c = pattern.charAt(i);
            if(c == '{'){
                stack.push(c);
            }else if (c == '}'){
                if(!stack.isEmpty()){
                    stack.pop();
                } else{
                    System.out.println("Error at - " + i);
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }
}

答案 14 :(得分:0)

Checking balanced parentheses
package parancheck;

import java.util.EmptyStackException;
import java.util.Stack;

public class ParnCheck 
{
    public static void main(String args[])
    {
        int pu = 0;
        int po = 0;
        String str = "()())";
        System.out.println(str); 
        Stack st = new Stack();
       for(int i=0; i<str.length();i++)
       {
        if(str.charAt(i)=='(')
        {
           doPush(st, str.charAt(i));
           pu++;
         }
        else 
        {
             try
              {
                doPop(st);
              }
             catch(EmptyStackException e)
              {
                System.out.println("");
              }
              po++;
        }
     }


       if(pu == po)
       {
           System.out.println("Correct");
       }
       else
       {
           System.out.println("Wrong");
       }

    }
    static void doPush(Stack st,char ch)
    {
        st.push(ch);
    }
    static void doPop(Stack st)
    {
        char c = (char)st.pop();
    }
}

答案 15 :(得分:0)

int i;
int len; 
char popped;
stack<char> st;
string a = "({<<";
len = a.length();

for(i=0;i<len;i++)
{
    if(a[i] == '<' || a[i] == '(' || a[i] == '[' || a[i] == '{')
    {
        st.push(a[i]); 
        continue;
    }
    if(a[i] == '>' || a[i] == ')' || a[i] == ']' || a[i] == '}')
    {
        if(st.empty())
        {
            cout << "stack is empty, when popped , not balanced" << endl;
            return 0;
        }
        else
        {
            popped = st.top(); 
            st.pop();
            if (!((a[i] == '>' && popped == '<') || (a[i] == ')' && popped == '(') || (a[i] == '}' && popped == '{') || (a[i] == '>' && popped == '<'))) //ok
            {
                cout << "not balanced on character" + std::string(1,a[i]) << endl;
                return 0;
            }
        }

    }

}
if(st.empty())
{
    cout << "balanced" << endl;
}
else
{
    cout << "not balanced stack not empty" << endl;
}

答案 16 :(得分:0)

为什么有返回值和out参数提供相同的信息?

你可以返回一个int:-1 = balanced,否则就是错误的索引。

答案 17 :(得分:0)

正如TheVillageIdiot所说,没关系。你也可以递归地实现它,这可能更优雅,也可能不是。最后,您可能希望要求匹配的括号中包含有效的内容,以便允许“(a)”但不允许“()”。