Valid Parentheses in an Expression
Given a string s containing three types of brackets {}, () and []. Determine whether the Expression are balanced or not.
An expression is balanced if each opening bracket has a corresponding closing bracket of the same type, the pairs are properly ordered and no bracket closes before its matching opening bracket.
- Balanced: "[()()]{}" → every opening bracket is closed in the correct order.
- Not balanced: "([{]})" → the ']' closes before the matching '{' is closed, breaking the nesting rule.
Example:
Input: s = "[{()}]"
Output: true
Explanation: All the brackets are well-formed.Input: s = "([{]})"
Output: false
Explanation: The expression is not balanced because there is a closing ']' before the closing '}'.
Table of Content
[Approach 1] Using Stack - O(n) Time and O(n) Space
We use a stack to ensure that every opening has a matching closing. Each opening is pushed onto the stack. When a closing appears, we check if the stack has a corresponding opening to pop; if not, the string is unbalanced. After processing the entire string, the stack must be empty for it to be considered balanced.
Illustration:
#include <iostream>
#include <stack>
#include <vector>
#include <string>
using namespace std;
bool isBalanced(string& s) {
stack<char> st;
for (char c : s) {
if (c == '(' || c == '{' || c == '[') {
st.push(c);
}
else if (c == ')' || c == '}' || c == ']') {
// No opening bracket
if (st.empty()) return false;
char top = st.top();
if ((c == ')' && top != '(') ||
(c == '}' && top != '{') ||
(c == ']' && top != '[')) {
return false;
}
// Pop matching opening bracket
st.pop();
}
}
// Balanced if stack is empty
return st.empty();
}
int main() {
string s="[()()]{}";
cout<<(isBalanced(s)?"true":"false");
return 0;
}
import java.util.Stack;
import java.util.Vector;
public class GFG {
public static boolean isBalanced(String s) {
Stack<Character> st = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(' || c == '{' || c == '[') {
st.push(c);
}
else if (c == ')' || c == '}' || c == ']') {
// No opening bracket
if (st.isEmpty()) return false;
char top = st.peek();
if ((c == ')' && top != '(') ||
(c == '}' && top != '{') ||
(c == ']' && top != '[')) {
return false;
}
// Pop matching opening bracket
st.pop();
}
}
// Balanced if stack is empty
return st.isEmpty();
}
public static void main(String[] args) {
String s = "[()()]{}";
System.out.println((isBalanced(s) ? "true" : "false"));
}
}
def isBalanced(s):
st = []
for c in s:
if c == '(' or c == '{' or c == '[':
st.append(c)
# Process closing brackets
elif c == ')' or c == '}' or c == ']':
# No opening bracket
if not st: return False
top = st[-1]
if ((c == ')' and top != '(') or
(c == '}' and top != '{') or
(c == ']' and top != '[')):
return False
# Pop matching opening bracket
st.pop()
# Balanced if stack is empty
return not st
if __name__ == '__main__':
s = "[()()]{}"
print("true" if isBalanced(s) else "false")
using System;
using System.Collections.Generic;
class GFG {
public static bool isBalanced(string s) {
Stack<char> st = new Stack<char>();
foreach (char c in s) {
if (c == '(' || c == '{' || c == '[') {
st.Push(c);
}
// Process closing brackets
else if (c == ')' || c == '}' || c == ']') {
// No opening bracket
if (st.Count == 0) return false;
char top = st.Peek();
if ((c == ')' && top != '(') ||
(c == '}' && top != '{') ||
(c == ']' && top != '[')) {
return false;
}
// Pop matching opening bracket
st.Pop();
}
}
// Balanced if stack is empty
return st.Count == 0;
}
public static void Main(string[] args) {
String s = "[()()]{}";
Console.WriteLine((isBalanced(s) ? "true" : "false"));
}
}
function isBalanced(s) {
let st = [];
for (let c of s) {
if (c === '(' || c === '{' || c === '[') {
st.push(c);
}
// Process closing brackets
else if (c === ')' || c === '}' || c === ']') {
// No opening bracket
if (st.length === 0) return false;
let top = st[st.length - 1];
if ((c === ')' && top !== '(') ||
(c === '}' && top !== '{') ||
(c === ']' && top !== '[')) {
return false;
}
// Pop matching opening bracket
st.pop();
}
}
// Balanced if stack is empty
return st.length === 0;
}
//Driven Code
let s = "[()()]{}";
console.log(isBalanced(s)?"true":"false");
Output
true
[Approach 2] Without using Stack - O(n) Time and O(1) Space
Instead of using an external stack, we can simulate stack operations directly on the input string by modifying it in place. A variable top is used to track the index of the last unmatched opening bracket. Whenever an opening bracket is found, it is placed at the next top position. For a closing bracket, we check if it matches the character at top. If it does, we simply decrement top; otherwise, the string is unbalanced. In the end, if top is -1, all brackets are matched and the string is balanced.
Note: Strings are immutable in Java, Python, C#, and JavaScript. Therefore, we cannot modify them in place, making this approach unsuitable for these languages.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool isBalanced(string& s) {
// stack top index in string
int top = -1;
for (int i = 0; i < s.length(); i++) {
if (s[i] == '(' || s[i] == '{' || s[i] == '[') {
// push opening bracket
s[++top] = s[i];
}
else if (s[i] == ')' || s[i] == '}' || s[i] == ']') {
// no opening bracket
if (top == -1) return false;
if ((s[i] == ')' && s[top] != '(') ||
(s[i] == '}' && s[top] != '{') ||
(s[i] == ']' && s[top] != '[')) {
return false;
}
top--;
}
}
// balanced if stack empty
return top == -1;
}
int main() {
string s="[()()]{}";
cout<<(isBalanced(s)?"true":"false");
}
Output
true