Walk a string of bracket characters. Push every opening bracket. On a closing bracket, pop and verify the popped opener matches. Mismatch or empty-stack pop means unbalanced; an empty stack at the end means balanced.

Algorithm

Canonical balanced input is "({[]})"; the stack grows to three elements then empties as the closers arrive in matching order.

Basic Implementation

basic.dart
void main() {
  final text = '({[]})';
  final pairs = <String, String>{')': '(', ']': '[', '}': '{'};
  final stack = <String>[];
  var balanced = true;
  for (var i = 0; i < text.length; i++) {
    final ch = text[i];
    if (ch == '(' || ch == '[' || ch == '{') {
      stack.add(ch);
    } else {
      if (stack.isEmpty || stack.last != pairs[ch]) {
        balanced = false;
        break;
      }
      stack.removeLast();
    }
  }
  if (stack.isNotEmpty) {
    balanced = false;
  }
  print(balanced);
}

Complexity

  • Time: O(n)
  • Space: O(n) worst case

Implementation notes

  • Dart: a growable List<String> is a fine stack — add / removeLast are O(1) amortized. stack.isEmpty / stack.last read the top without leaking the underlying storage.
  • The replay shows the current character, the operation (push vs. pop), and the post-step stack contents using a literal [(, {, [] notation rather than any object identity.
push opener pop matching closer Each closing bracket must match the most recent unmatched opener.