Checking string has balanced parentheses

后端 未结 18 2329
谎友^
谎友^ 2020-12-01 08:42

I am reading the Algorithm Design Manual Second Edition and this is from an exercise question. Quoting the question

A common problem for comp

相关标签:
18条回答
  • 2020-12-01 08:45

    C# 7 or so now also has tuples. You don't need the out argument anymore. As many others pointed out, there is no need for a stack or a queue or alike.
    Just a balance counter suffices.

        -- 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
    
    

    Side note: The syntax highlighting for Haskell here needs some improvement, right? :)

    0 讨论(0)
  • 2020-12-01 08:46
    1. Remove all non-'(' and -')' characters from an input string. This gives you a string of '(' and ')' only.

    2. If the string has odd length, return false.

    3. Else, start reading along our string, adding +1 to a "signature" for each '(' and -1 for each ')'; if this signature is ever negative, return false.

    4. Return true.

    0 讨论(0)
  • 2020-12-01 08:48

    Piggy back on @Russell's idea:

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-01 08:54

    Time order O(n) and spatial order 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;
    }
    
    0 讨论(0)
  • 2020-12-01 08:55
    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-01 08:55

    Here's a one liner for C# using System.Linq:

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

    it utilizes the fact that string is in fact IEnumerable of chars so we can run Aggregate function on it. We increase the counter by 1 when we encounter the '(' char and decrease it by 1 on ')' char. Once we reach the negative value of -1 we stay there to indicate the invalid state.

    It doesn't have any early exit implemented so it will be slower than most implementations presented here but maybe someone will find it useful :)

    0 讨论(0)
提交回复
热议问题