def is_paired(input_string):
bracket_map = {"]" : "[", "}": "{", ")":"("}
stack = []
for element in input_string:
if element in bracket_map.values():
stack.append(element)
if element in bracket_map:
if not stack or (stack.pop() != bracket_map[element]):
return False
return not stack
The point of this approach is to maintain a context of which bracket sets are currently "open":
- If a left bracket is found, push it onto the stack (append it to the
list
). - If a right bracket is found, and it pairs with the last item placed on the stack, pop the bracket off the stack and continue.
- If there is a mismatch, for example
'['
with'}'
or there is no left bracket on the stack, the code can immediately terminate and returnFalse
. - When all the input text is processed, determine if the stack is empty, meaning all left brackets were matched.
In Python, a [list
]lists is a good implementation of a stack: it has list.append()
(equivalent to a "push") and lsit.pop()
methods built in.
Some solutions use collections.deque()
as an alternative implementation, though this has no clear advantage (since the code only uses appends to the right-hand side) and near-identical runtime performance.
The default iteration for a dictionary is over the keys, so the code above uses a plain bracket_map
to search for right brackets, while bracket_map.values()
is used to search for left brackets.
Other solutions created two sets of left and right brackets explicitly, or searched a string representation:
if element in ']})':
Such changes made little difference to code length or readability, but ran about 5-fold faster than the dictionary-based solution.
At the end, success is an empty stack, tested above by using the False-y quality of []
(as Python programmers often do).
To be more explicit, we could alternatively use an equality:
return stack == []