Minimum Additions for Valid Parentheses
Last Updated :
13 Sep, 2025
Given a string s consisting of parentheses '(' and ')'. Find the minimum number of parentheses (either '(' or ')') that must be added at any positions to make the string s a valid parentheses string.
A string is valid if every opening parenthesis has a corresponding closing parenthesis and they are properly nested.
Examples:
Input: s = "(()("
Output: 2
Explanation: Two '(' are left unmatched, so we need two ')' to balance.
Input: s = ")))"
Output: 3
Explanation: Three '(' need to be added at the end to make the string valid.
[Approach 1] Using Stack - O(n) Time and O(n) Space
The idea is to use the concept of valid parentheses. For every opening parenthesis, a matching closing parenthesis will remove it from the stack. At the end, only the unmatched parentheses remain in the stack, and their count gives the number of insertions needed to make the string valid.
At the end of the string:
- Every '(' left in the stack needs a ')' to become valid.
- Every ')' left in the stack needs a '(' to become valid.
Hence, the minimum number of insertions needed = number of unmatched parentheses = stack size.
C++
#include <iostream>
#include <stack>
using namespace std;
int minParentheses(string& s) {
stack<char> st;
for (int i = 0; i < s.size(); i++) {
if (!st.empty()) {
if (s[i] == '(')
st.push('(');
else if (st.top() == '(')
// matched pair, remove from stack
st.pop();
else
// unmatched closing parenthesis
st.push(s[i]);
} else {
st.push(s[i]);
}
}
return st.size();
}
int main() {
string s = "(()(";
cout << minParentheses(s);
}
Java
import java.util.Stack;
public class GfG {
static int minParentheses(String s) {
Stack<Character> st = new Stack<>();
for (int i = 0; i < s.length(); i++) {
if (!st.isEmpty()) {
if (s.charAt(i) == '(')
st.push('(');
else if (st.peek() == '(')
// matched pair, remove from stack
st.pop();
else
// unmatched closing parenthesis
st.push(s.charAt(i));
} else {
st.push(s.charAt(i));
}
}
return st.size();
}
public static void main(String[] args) {
String s = "(()(";
System.out.println(minParentheses(s));
}
}
Python
def minParentheses(s):
st = []
for i in range(len(s)):
if st:
if s[i] == '(':
st.append('(')
elif st[-1] == '(':
# matched pair, remove from stack
st.pop()
else:
# unmatched closing parenthesis
st.append(s[i])
else:
st.append(s[i])
return len(st)
if __name__ == "__main__":
s = "(()("
print(minParentheses(s))
C#
using System;
using System.Collections.Generic;
public class GfG {
static int minParentheses(string s) {
Stack<char> st = new Stack<char>();
for (int i = 0; i < s.Length; i++) {
if (st.Count > 0) {
if (s[i] == '(')
st.Push('(');
else if (st.Peek() == '(')
// matched pair, remove from stack
st.Pop();
else
// unmatched closing parenthesis
st.Push(s[i]);
} else {
st.Push(s[i]);
}
}
return st.Count;
}
public static void Main() {
string s = "(()(";
Console.WriteLine(minParentheses(s));
}
}
JavaScript
function minParentheses(s) {
let st = [];
for (let i = 0; i < s.length; i++) {
if (st.length > 0) {
if (s[i] === '(')
st.push('(');
else if (st[st.length - 1] === '(')
// matched pair, remove from stack
st.pop();
else
// unmatched closing parenthesis
st.push(s[i]);
} else {
st.push(s[i]);
}
}
return st.length;
}
// Driver Code
let s = "(()(";
console.log(minParentheses(s));
[Approach 2] Using Counter / Balance Method - O(n) Time and O(1) Space
The idea is to track unmatched parentheses using counters instead of a stack. We keep a balance for unmatched '(' and a counter for unmatched ')'. Whenever balance goes negative, it means there is an extra closing parenthesis, so we increase the unmatched closing counter and reset balance. At the end, the total insertions required is the sum of remaining unmatched '(' and unmatched ')'.
C++
#include <iostream>
#include <string>
using namespace std;
int minParentheses(string &s) {
int balance = 0;
int unmatchedClosing = 0;
for (int i = 0; i < s.size(); ++i) {
// if current char is '(', increment balance
if (s[i] == '(') {
balance++;
}
// if current char is ')', decrement balance
else if (s[i] == ')') {
balance--;
// if balance becomes negative, unmatched ')'
if (balance < 0) {
// increment unmatched closing counter
unmatchedClosing++;
balance = 0;
}
}
}
// total additions = remaining '(' + unmatched ')'
return balance + unmatchedClosing;
}
int main() {
string s ="(()(";
cout << minParentheses(s) << endl;
return 0;
}
Java
public class GfG {
static int minParentheses(String s) {
int balance = 0;
int unmatchedClosing = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// if current char is '(', increment balance
if (c == '(') {
balance++;
}
// if current char is ')', decrement balance
else if (c == ')') {
balance--;
// if balance becomes negative, unmatched ')'
if (balance < 0) {
unmatchedClosing++;
balance = 0;
}
}
}
// total additions = remaining '(' + unmatched ')'
return balance + unmatchedClosing;
}
public static void main(String[] args) {
String s = "(()(";
System.out.println(minParentheses(s));
}
}
Python
def minParentheses(s):
balance = 0
unmatchedClosing = 0
for c in s:
# if current char is '(', increment balance
if c == '(':
balance += 1
# if current char is ')', decrement balance
elif c == ')':
balance -= 1
# if balance becomes negative, unmatched ')'
if balance < 0:
# increment unmatched closing counter
unmatchedClosing += 1
balance = 0
# total additions = remaining '(' + unmatched ')'
return balance + unmatchedClosing
if __name__ == "__main__":
s = "(()("
print(minParentheses(s))
C#
using System;
public class GfG {
static int minParentheses(string s) {
int balance = 0;
int unmatchedClosing = 0;
foreach (char c in s) {
// if current char is '(', increment balance
if (c == '(') {
balance++;
}
// if current char is ')', decrement balance
else if (c == ')') {
balance--;
// if balance becomes negative, unmatched ')'
if (balance < 0) {
// increment unmatched closing counter
unmatchedClosing++;
balance = 0;
}
}
}
// total additions = remaining '(' + unmatched ')'
return balance + unmatchedClosing;
}
public static void Main(string[] args) {
string s = "(()(";
Console.WriteLine(minParentheses(s));
}
}
JavaScript
function minParentheses(s) {
let balance = 0;
let unmatchedClosing = 0;
for (let c of s) {
// if current char is '(', increment balance
if (c === '(') {
balance++;
}
// if current char is ')', decrement balance
else if (c === ')') {
balance--;
// if balance becomes negative, unmatched ')'
if (balance < 0) {
// increment unmatched closing counter
unmatchedClosing++;
balance = 0;
}
}
}
// total additions = remaining '(' + unmatched ')'
return balance + unmatchedClosing;
}
// Driver Code
let s = "(()(";
console.log(minParentheses(s));
[Approach 3] Using Two-Pass Counting Method - O(n) Time and O(1) Space
The idea is to scan the string twice first left to right to count unmatched ')', then right to left to count unmatched '('. The sum of these two counts gives the minimum insertions needed to make the string valid.
C++
#include <iostream>
#include <string>
using namespace std;
int minParentheses(string &s) {
int n = s.size();
int unmatchedClosing = 0;
int balance = 0;
// first pass: left to right
for (int i = 0; i < s.size(); ++i) {
// if current char is '(', increment balance
if (s[i] == '(') {
balance++;
}
// if current char is ')', decrement balance
else if (s[i] == ')'){
balance--;
// if balance becomes negative, unmatched ')'
if (balance < 0) {
unmatchedClosing++;
balance = 0;
}
}
}
// second pass: right to left to count unmatched '('
int unmatchedOpening = 0;
balance = 0;
for (int i = n - 1; i >= 0; i--) {
// if current char is ')', increment balance
if (s[i] == ')') {
balance++;
}
// if current char is '(', decrement balance
else if (s[i] == '(') {
balance--;
// if balance becomes negative, unmatched '('
if (balance < 0) {
unmatchedOpening++;
balance = 0;
}
}
}
// total additions = unmatched ')' + unmatched '('
return unmatchedClosing + unmatchedOpening;
}
int main() {
string s = "(()(";
cout << minParentheses(s) << endl;
return 0;
}
Java
public class GfG {
static int minParentheses(String s) {
int n = s.length();
int unmatchedClosing = 0;
int balance = 0;
// first pass: left to right
for (int i = 0; i < s.length(); ++i) {
// if current char is '(', increment balance
if (s.charAt(i) == '(') {
balance++;
}
// if current char is ')', decrement balance
else if (s.charAt(i) == ')') {
balance--;
// if balance becomes negative, unmatched ')'
if (balance < 0) {
unmatchedClosing++;
balance = 0;
}
}
}
// second pass: right to left to count unmatched '('
int unmatchedOpening = 0;
balance = 0;
for (int i = n - 1; i >= 0; i--) {
// if current char is ')', increment balance
if (s.charAt(i) == ')') {
balance++;
}
// if current char is '(', decrement balance
else if (s.charAt(i) == '(') {
balance--;
// if balance becomes negative, unmatched '('
if (balance < 0) {
unmatchedOpening++;
balance = 0;
}
}
}
// total additions = unmatched ')' + unmatched '('
return unmatchedClosing + unmatchedOpening;
}
public static void main(String[] args) {
String s = "(()(";
System.out.println(minParentheses(s));
}
}
Python
def minParentheses(s):
n = len(s)
unmatchedClosing = 0
balance = 0
# first pass: left to right
for c in s:
# if current char is '(', increment balance
if c == '(':
balance += 1
# if current char is ')', decrement balance
elif c == ')':
balance -= 1
# if balance becomes negative, unmatched ')'
if balance < 0:
unmatchedClosing += 1
balance = 0
# second pass: right to left to count unmatched '('
unmatchedOpening = 0
balance = 0
for c in reversed(s):
# if current char is ')', increment balance
if c == ')':
balance += 1
# if current char is '(', decrement balance
elif c == '(':
balance -= 1
# if balance becomes negative, unmatched '('
if balance < 0:
unmatchedOpening += 1
balance = 0
# total additions = unmatched ')' + unmatched '('
return unmatchedClosing + unmatchedOpening
if __name__ == "__main__":
s = "(()("
print(minParentheses(s))
C#
using System;
public class GfG {
static int minParentheses(string s) {
int n = s.Length;
int unmatchedClosing = 0;
int balance = 0;
// first pass: left to right
foreach (char c in s) {
// if current char is '(', increment balance
if (c == '(') {
balance++;
}
// if current char is ')', decrement balance
else if (c == ')') {
balance--;
// if balance becomes negative, unmatched ')'
if (balance < 0) {
unmatchedClosing++;
balance = 0;
}
}
}
// second pass: right to left to count unmatched '('
int unmatchedOpening = 0;
balance = 0;
for (int i = n - 1; i >= 0; i--) {
// if current char is ')', increment balance
if (s[i] == ')') {
balance++;
}
// if current char is '(', decrement balance
else if (s[i] == '(') {
balance--;
// if balance becomes negative, unmatched '('
if (balance < 0) {
unmatchedOpening++;
balance = 0;
}
}
}
// total additions = unmatched ')' + unmatched '('
return unmatchedClosing + unmatchedOpening;
}
public static void Main(string[] args) {
string s = "(()(";
Console.WriteLine(minParentheses(s));
}
}
JavaScript
function minParentheses(s) {
let n = s.length;
let unmatchedClosing = 0;
let balance = 0;
// first pass: left to right
for (let c of s) {
// if current char is '(', increment balance
if (c === '(') {
balance++;
}
// if current char is ')', decrement balance
else if (c === ')') {
balance--;
// if balance becomes negative, unmatched ')'
if (balance < 0) {
unmatchedClosing++;
balance = 0;
}
}
}
// second pass: right to left to count unmatched '('
let unmatchedOpening = 0;
balance = 0;
for (let i = n - 1; i >= 0; i--) {
// if current char is ')', increment balance
if (s[i] === ')') {
balance++;
}
// if current char is '(', decrement balance
else if (s[i] === '(') {
balance--;
// if balance becomes negative, unmatched '('
if (balance < 0) {
unmatchedOpening++;
balance = 0;
}
}
}
// total additions = unmatched ')' + unmatched '('
return unmatchedClosing + unmatchedOpening;
}
// Driver Code
let s = "(()(";
console.log(minParentheses(s));
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem