Skip to content

Longest Valid Parentheses

Understanding the Longest Valid Parentheses Problem

The problem of finding the “Longest Valid Parentheses” is a classic challenge in coding interviews and competitive programming. It involves determining the longest substring of valid parentheses from a given string composed solely of open ‘(‘ and closed ‘)’ parentheses. This blog will explore various approaches to solve this problem, including brute force, stack-based techniques, and dynamic programming. Each method has its own advantages and trade-offs, and understanding them will enhance your problem-solving skills.

Problem Statement

The task is simple: Given a string consisting of only ‘(‘ and ‘)’, find the length of the longest valid (well-formed) parentheses substring. For example, in the string “(()”, the longest valid substring is of length 2, while in “())”, it is 2 again. A string like “((()))” would yield a valid length of 6, and an empty string would return 0.

Examples

  • Input: “()” → Output: 2
  • Input: “(())” → Output: 4
  • Input: “)(” → Output: 0
  • Input: “(()))” → Output: 4

Understanding the Constraints

Before diving into solutions, it’s crucial to understand the constraints of the problem. The main challenge lies in efficiently determining the length of valid parentheses without unnecessary computations. The naive approach might involve checking all possible substrings, but this can lead to inefficiencies as the string length increases.

Approach 1: Brute Force Method

The brute force method involves examining every possible substring to check if it is valid. This can be implemented using two nested loops: one to pick the starting index and another to pick the ending index of the substring.

Brute Force Steps

  1. Iterate through each starting index in the string.
  2. For each starting index, iterate through possible ending indices, ensuring the substring has at least two characters.
  3. Check if the substring is valid using a helper function.
  4. Keep track of the maximum length found.

However, the time complexity of this approach is O(n³) due to the triple loops (two for substring selection and one for validation), while the space complexity is O(n) for storing the valid substrings.

Approach 2: Using a Stack

The stack-based approach is more efficient and commonly used for problems involving parentheses. This method leverages a stack to keep track of indices of the parentheses and determine valid lengths.

Stack-Based Steps

  1. Initialize a stack and push -1 onto it, which acts as a base for valid substring calculations.
  2. Iterate through the string:
    • If the character is ‘(‘, push its index onto the stack.
    • If the character is ‘)’:
      • Pop the top of the stack.
      • If the stack is empty after popping, push the current index.
      • If the stack is not empty, calculate the length of the valid substring as the difference between the current index and the index at the top of the stack.
  3. Keep track of the maximum length found during the iterations.

This approach runs in O(n) time complexity and O(n) space complexity due to the stack usage.

Java Implementation of the Stack Approach

Below is the Java code that implements the stack-based solution:

public class LongestValidParentheses {
    public int longestValidParentheses(String s) {
        Stack stack = new Stack<>();
        stack.push(-1);
        int maxLength = 0;

        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                stack.push(i);
            } else {
                stack.pop();
                if (stack.isEmpty()) {
                    stack.push(i);
                } else {
                    maxLength = Math.max(maxLength, i - stack.peek());
                }
            }
        }
        return maxLength;
    }
}

Approach 3: Two-Pass Method

This method optimizes the previous approaches by eliminating the need for stack space. It uses two passes through the string to count open and closed parentheses.

Two-Pass Steps

  1. In the first pass (left to right), count open and closed parentheses.
  2. When counts are equal, update the maximum length. If closed exceeds open, reset both counts.
  3. In the second pass (right to left), do the same but swap the roles of open and closed counts.

This method runs in O(n) time complexity and O(1) space complexity, making it very efficient.

Dynamic Programming Approach

The dynamic programming approach utilizes an array to store the lengths of valid parentheses substrings ending at each index.

Dynamic Programming Steps

  1. Initialize a DP array of length equal to the input string, filled with zeros.
  2. Iterate through the string:
    • If the character is ‘(‘, skip it since no valid substring can end there.
    • If the character is ‘)’, check the previous characters to determine if a valid substring can be formed.
    • Update the DP array with the length of the valid substring.
  3. The maximum value in the DP array will be the answer.

This method also has O(n) time complexity and O(n) space complexity due to the DP array.

Conclusion

In conclusion, the “Longest Valid Parentheses” problem can be tackled using various approaches, each with its own strengths. The brute force method is straightforward but inefficient for large strings. The stack-based and two-pass methods offer efficient solutions with linear time complexity. Lastly, the dynamic programming approach provides a systematic way to build up solutions. Choosing the right approach depends on specific constraints and requirements of the problem at hand.

For visual learners, you can find useful video content related to this topic on YouTube.

Thank you for reading, and happy coding!

Algorithms made easy