Chapter 24 : Stack (Pat 2)

In this chapter of the Java with DSA series, we dive deeper into stacks, tackling some advanced problems that frequently appear in technical interviews and competitive programming. We'll explore practical applications of stacks in solving parenthesis problems, evaluating duplicate parentheses, and computing the maximum rectangular area in a histogram. Each concept is paired with detailed explanations and Java code implementations to ensure a comprehensive understanding.


What You’ll Learn in This Chapter

  1. Valid Parenthesis Problem

    • Understand how to determine if a sequence of parentheses (and other brackets) is valid.

    • Implement the solution using stacks efficiently.

  2. Duplicate Parentheses Problem

    • Detect unnecessary pairs of parentheses in an expression.

    • Optimize solutions using stack-based logic.

  3. Maximum Rectangular Area in a Histogram

    • Learn to calculate the largest rectangle that can fit in a histogram using stacks.
  4. Practice Questions

    • Test your knowledge with additional problems and their solutions.

1. Valid Parenthesis

A valid parenthesis sequence is one where every opening parenthesis has a corresponding and correctly ordered closing parenthesis. For example:

  • Valid: (()), {[()]}, [()]

  • Invalid: ((, {[}], [)(]

Approach

  • Use a stack to track unmatched opening brackets.

  • Traverse the string and push opening brackets into the stack.

  • For every closing bracket, check if it matches the last opening bracket using the stack.

Code

import java.util.Stack;

public class ValidParenthesis {
    public static boolean isValid(String str) {
        Stack<Character> stack = new Stack<>();
        for (char ch : str.toCharArray()) {
            if (ch == '(' || ch == '{' || ch == '[') {
                stack.push(ch);
            } else {
                if (stack.isEmpty()) return false;
                char top = stack.pop();
                if ((ch == ')' && top != '(') ||
                    (ch == '}' && top != '{') ||
                    (ch == ']' && top != '[')) {
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }

    public static void main(String[] args) {
        String expression = "{[()]}";
        System.out.println(isValid(expression) ? "Valid" : "Invalid");
    }
}

2. Duplicate Parenthesis

Detecting duplicate parentheses involves finding expressions where parentheses are unnecessarily repeated, such as ((a+b)).

Approach

  • Push characters onto a stack until a closing parenthesis ) is encountered.

  • Check the elements inside the parentheses; if there are fewer than two elements (besides the opening bracket), it's a duplicate.

Code

import java.util.Stack;

public class DuplicateParenthesis {
    public static boolean hasDuplicateParentheses(String str) {
        Stack<Character> stack = new Stack<>();
        for (char ch : str.toCharArray()) {
            if (ch == ')') {
                int count = 0;
                while (stack.peek() != '(') {
                    stack.pop();
                    count++;
                }
                stack.pop(); // Remove the '('
                if (count < 1) return true; // Duplicate parentheses
            } else {
                stack.push(ch);
            }
        }
        return false;
    }

    public static void main(String[] args) {
        String expression = "((a+b))";
        System.out.println(hasDuplicateParentheses(expression) ? "Has duplicates" : "No duplicates");
    }
}

3. Maximum Rectangular Area in Histogram

Given a histogram represented by an array of heights, find the largest rectangular area that can fit under the histogram.

Approach

  1. Use stacks to calculate the nearest smaller heights to the left and right for each bar.

  2. For each bar, calculate the maximum rectangle it can contribute using the formula: Area=Height×(Right_Index−Left_Index−1)\text{Area} = \text{Height} \times (\text{Right\_Index} - \text{Left\_Index} - 1)

Code

import java.util.Stack;

public class MaxRectHistogram {
    public static int getMaxArea(int[] heights) {
        int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        Stack<Integer> stack = new Stack<>();

        // Calculate nearest smaller to left
        for (int i = 0; i < n; i++) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                stack.pop();
            }
            left[i] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }

        stack.clear(); // Reset stack

        // Calculate nearest smaller to right
        for (int i = n - 1; i >= 0; i--) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                stack.pop();
            }
            right[i] = stack.isEmpty() ? n : stack.peek();
            stack.push(i);
        }

        // Calculate max area
        int maxArea = 0;
        for (int i = 0; i < n; i++) {
            int width = right[i] - left[i] - 1;
            maxArea = Math.max(maxArea, heights[i] * width);
        }

        return maxArea;
    }

    public static void main(String[] args) {
        int[] histogram = {2, 1, 5, 6, 2, 3};
        System.out.println("Maximum Area: " + getMaxArea(histogram));
    }
}

4. Practice Questions


Conclusion

In this chapter, we explored:

  • How stacks can be used to solve bracket and histogram problems.

  • Efficient techniques for implementing these solutions in Java.

  • Hands-on practice to strengthen your grasp of stack-based algorithms.

Related Posts in My Series:

DSA in Java Series:

  • Chapter 2: Operators in Java – Learn about the different types of operators in Java, including arithmetic, relational, logical, and assignment operators, along with examples to understand their usage.

  • Chapter 33: Trie in Java – Explore the implementation and use of Trie data structure in Java, a powerful tool for handling strings, with practical coding examples.

Other Series:

  • Full Stack Java Development – Master the essentials of Java programming and web development with this series. Topics include object-oriented programming, design patterns, database interaction, and more.

  • Full Stack JavaScript Development – Become proficient in JavaScript with this series covering everything from front-end to back-end development, including frameworks like React and Node.js.


Connect with Me
Stay updated with my latest posts and projects by following me on social media:

Your feedback and engagement are invaluable. Feel free to reach out with questions, comments, or suggestions. Happy coding!


Rohit Gawande
Full Stack Java Developer | Blogger | Coding Ent