需要检查给定数组中的花括号是否平衡

时间:2019-01-16 17:38:01

标签: swift string braces

如果满足以下条件,则认为字符串中的花括号是平衡的

  1. 所有括号必须闭合。大括号以(), {}, []的形式出现。左括号打开该对,右括号将其关闭。
  2. 在任何一组嵌套括号中,任何一对之间的括号都必须闭合。

例如,[{}]是大括号的有效分组,而[}]{}不是大括号。

我尝试了以下代码段,但未获得预期的结果,

let firstBracketOpening = "("
let firstBracketClosing = ")"

let secondBracketOpening = "{"
let secondBracketClosing = "}"

let thirdBracketOpening = "["
let thirdBracketClosing = "]"

func check(for braces: String) -> Bool {
    var isMissing = false
    for char in brace {
        isMissing = contains(char: char, in: brace)
        if isMissing {
            break
        }
    }        
    return isMissing ? false : true
}

func contains(char: Character, in string: String) -> Bool {
    var isMissing = false

    if firstBracketOpening.contains(char) {
        isMissing = string.contains(firstBracketClosing) ? false : true
    }

    if secondBracketOpening.contains(char) {
        isMissing = string.contains(secondBracketClosing) ? false : true
    }

    if thirdBracketOpening.contains(char) {
        isMissing = string.contains(thirdBracketClosing) ? false : true
    }

    return isMissing
}

任何解决方案的线索将不胜感激。预先感谢。

5 个答案:

答案 0 :(得分:8)

这是我想出的解决方案:

func checkParentheses(s: String) -> Bool {
    let pairs: [Character: Character] = ["(": ")", "[": "]", "{": "}"]
    var stack: [Character] = []
    for char in s {
        if let match = pairs[char] {
            stack.append(match)
        } else if stack.last == char {
            stack.popLast()
        } else {
            return false
        }
    }
    return stack.isEmpty
}

测试用例:

print(checkParentheses(s: "((({[]})))")) // True (Balanced)
print(checkParentheses(s: "((({[]}))")) // False (Not Balanced)
print(checkParentheses(s: "(]")) // False (Not Balanced)

我们在这里所做的只是迭代Character中的每个String。如果找到起始括号,即。 “(”,然后将结尾括号推入堆栈,即“)”。只要当前字符是起始括号,我们就这样做。

一旦找到结尾括号,根据我们添加括号的方式,它必须是堆栈中的最后一个字符。如果是这样,则括号是有效的,我们可以继续进行。

如果以上所有条件都不成立,则可能是字符无效(不是括号),或者括号不平衡的情况。话虽如此,我们可以return false在这里。

遍历String中的每个字符后,如果括号是平衡的,我们的堆栈将为空。如果堆栈不为空,则表示括号不平衡。

答案 1 :(得分:4)

要正确执行此操作,您需要一个stack来保持左大括号。当您获得一个开口撑杆时,将其推入堆栈。当您得到一个闭合括号时,从堆栈中弹出顶部的开口括号并检查它们是否匹配。解析完字符串后,stack应该为空。

enum Balance {
    case balanced
    case unbalanced(String)
}

func checkBalance(_ str: String) -> Balance {
    var stack = [Character]()

    for char in str {
        if ["{", "(", "["].contains(char) {
            stack.append(char)
        } else if ["}", ")", "]"].contains(char) {
            if let top = stack.popLast() {
                switch (top, char) {
                case ("{", "}"), ("(", ")"), ("[", "]"):
                    break
                default:
                    return .unbalanced("mismatched braces: \(top), \(char)")
                }
            } else {
                return .unbalanced("unexpected close brace: \(char)")
            }
        }
    }
    if !stack.isEmpty {
        return .unbalanced("missing \(stack.count) closing braces")
    }
    return .balanced
}

测试

checkBalance("{ [ ( ) ] }")
.balanced
checkBalance("{ [ ] { } }")
.balanced
checkBalance("[(")
.unbalanced("missing 2 closing braces")
checkBalance("{ [ ( ) }")
.unbalanced("mismatched braces: [, }")
checkBalance("}")
.unbalanced("unexpected close brace: }")

注意:

checkBalance返回类型为Balance的枚举。要检查结果是否为.balanced,您可以这样做:

if case .balanced = checkBalance("() { [ ] }") {
    // handle balanced case
} 

或者您可以使用switch

switch checkBalance("() { [ ] }") {
case .balanced:
    // do something if balanced
case .unbalanced(let reason):
    print("Not balanced: \(reason)")
}

答案 2 :(得分:3)

import Foundation

extension String {

    func isBalanced() -> Bool {
        switch self.filter("()[]{}".contains)
            .replacingOccurrences(of: "()", with: "")
            .replacingOccurrences(of: "[]", with: "")
            .replacingOccurrences(of: "{}", with: "") {
        case "": return true
        case self: return false
        case let next: return next.isBalanced()
        }
    }

}

说明:

  1. filter("()[]{}".contains)删除除定界符之外的所有字符。它的含义与filter({ c in "()[]{}".contains(c) })相同。

  2. 任何有限长度的非空平衡字符串必须包含一个或多个空的定界符对(()[]{})。删除所有空对不会改变字符串的平衡度。因此,请使用replacingOccurrences(of:with:)删除所有此类空对。

  3. 如果在删除所有空对之后,您有一个空字符串,然后从一个平衡字符串开始,则返回true。

  4. 如果在删除所有空对之后,您实际上没有删除任何空对(并且您没有空字符串),那么您必须具有不平衡的定界符,因此返回false。

  5. 如果删除所有空对后,至少删除了一对,那么现在可能已有新的空对。例如,删除[({})][({})]的空对将得到[()][()],其中有新的空对。因此,尝试通过递归调用isBalanced尾部来进行更多删除。

答案 3 :(得分:0)

只是为了好玩。可能不包含长字符串(大约60个级别的左字符,但理想情况下适合大多数编辑情况)。

与堆叠方式相同。 2个整数构成一个堆栈。 00为空,每个最右边的数字分别代表11、01、10,表示“(”,“ [”和“ {”。告诉我是否有错误。希望它的运行速度快于概念堆栈。

例如,“((({} [])))” 最初,两个堆栈整数均为0 0。

        0 0
 "(" -> 1 1.  (  0<<1 + 1 , 0<<1 + 1 ) //push
 "(" -> 3 3   (  1<<1 + 1 , 1<<1 + 1 ) //push
 "{" -> 7 6.  (  3<<1 + 1,  3<<1 + 0 ) //push
 "}" -> 3 3.  (  7>>1 ,  6 >>1) //pop
 "[" -> 6 7.  (  3<<1 + 0, 3<<1 + 1) //push
 "]" -> 3 3.  (  6>>1 , 7>>1 ) //pop
 ")" -> 1 1.  (  3>>1 , 3>>1 ) //pop
 ")" -> 0 0.  (  1>>1 , 1>>1 ) //pop

平衡。

    func test(_ s: String) -> Bool{
        var os1 : Int = 0;   var os2 : Int = 0
        for c in s{
            switch (c, os1 & 0x1, os2 & 0x1) {
            case ("(",_,_):  os1 <<= 0x1 ;  os1 |= 0x1 ; os2 <<= 0x1 ; os2 |= 0x1
            case ("[",_,_):  os1 <<= 0x1 ;  os1 |= 0x0 ; os2 <<= 0x1 ; os2 |= 0x1
            case ("{", _,_): os1 <<= 0x1 ;  os1 |= 0x1 ; os2 <<= 0x1 ; os2 |= 0x0
            case (")",0x1, 0x1), ("]",0x0, 0x1),("}",0x1, 0x0):  os1 >>= 0x1 ;  os2 >>= 0x1
            case (")",_ ,_),("]", _, _), ("}", _, _):  return false
            default: break
            }
        }
        return os1 == 0 && os2 == 0
    }


    print (test("[((([])))]"))
    print (test("[[[[]]]][[[[]]]]")) 

将传递其他字符,因此可以在开发情况下使用。

    print (test("[((hello([]))my)]")) 

答案 4 :(得分:0)

Aand,一个完全FP解决方案,使用堆栈来跟踪不平衡的括号:

extension StringProtocol {
    func correctlyClosedParentheses() -> Bool {
        return reduce([Character]()) { stack, char in
            switch (char, stack.last) {
            // opening parentheses, we don't care about the top of the stack
            case ("(", _), ("[", _), ("{", _): return stack + [char]
                
            // closing parentheses, we do care about the top of the stack
            case (")", "("), ("]", "["), ("}", "{"): return stack.dropLast()
                
            // closing parentheses that failed the top of the stack check
            // we just accumulate them to make sure the stack is invalid
            case (")", _), ("]", _), ("}", _): return stack + [char]
                
            // other characters, we don't care about them
            default: return stack
            }
        }.isEmpty
    }
}