Valid Parentheses - Complete Solution Guide
Valid Parentheses is LeetCode problem 20, a Easy level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Given a string s containing just the characters '(' , ')' , '{' , '}' , '[' and ']' , determine if the input string is valid. An input string is valid if: Open brackets must be closed by the same type of brackets. Open brackets must be closed in the correct order. Every close bracket has a corresponding open bracket of the same type. Example 1: Input: s = "()" Output: true Example 2: Input: s = "()[]{}" Output: true Example 3: Input: s = "(]" Output: false Example 4: Input: s = "([])" Output: tr
Detailed Explanation
The "Valid Parentheses" problem challenges us to determine if a given string, composed solely of bracket characters like `(`, `)`, `{`, `}`, `[`, and `]`, is well-formed. This isn't just about ensuring an equal count of opening and closing brackets; it's crucially about their *order* and *type*. Specifically, three rules must be upheld: an open bracket must be closed by its *same type* (e.g., `(` by `)`, not `]`), brackets must be closed in the *correct nesting order* (e.g., `([{}])` is valid, but `([)]` is not), and every closing bracket must have a *corresponding open bracket* of the same type preceding it. Consider a string like `"([)]"`: while it has an equal number of open and close parentheses and square brackets, the `)` closes `(` *before* `[` is closed, violating the order. This makes the problem less about simple counting and more about managing expectations for closures.
Solution Approach
The most intuitive and elegant approach for this problem leverages a stack, mirroring how we mentally process bracket sequences. When iterating through the input string, if we encounter an *opening* bracket (`(`, `{`, `[`), we push it onto our stack. This essentially means we're "expecting" its corresponding closing bracket at some point in the future. If we instead encounter a *closing* bracket (`)`, `}`, `]`): we immediately need to check if it's the right type to close the *most recently opened* bracket. We achieve this by popping the top element from our stack. If the stack was empty when we encountered a closing bracket (e.g., `"]"`), or if the popped open bracket doesn't match the type of the current closing bracket (e.g., popping `[` for a `)`), the string is invalid. If they match, we continue. After processing the entire string, if our stack is empty, it means every opened bracket found its proper closure; otherwise, if there are still elements on the stack (e.g., `"((("`), it implies some brackets were opened but never closed, rendering the string invalid.
Step-by-Step Algorithm
- Initialize an empty stack.
- Iterate through the input string `s` character by character.
- If the character is an opening parenthesis ('(', '[', or '{'), push it onto the stack.
- If the character is a closing parenthesis (')', ']', or '}'), check if the stack is empty. If empty, return `false` (no matching opening parenthesis).
- If the stack is not empty, pop the top element from the stack.
- Check if the popped element matches the current closing parenthesis. If they don't match, return `false`.
- After the loop, if the stack is empty, return `true`; otherwise, return `false` (unmatched opening parentheses).
Key Insights
- **Stack as a Memory for Unclosed Brackets:** The core insight is that a stack perfectly models the LIFO (Last-In, First-Out) nature of bracket nesting. When you open a bracket, you 'expect' its closure. If you open another one before closing the first, the *newest* opening bracket is the one you must close *first*. The stack stores these 'pending' open brackets in the correct order for future matching.
- **Efficient Type Mapping and Empty Stack Grace:** Utilizing a hash map (like `mapping` here) to quickly associate closing brackets with their required opening types (`')': '('`, etc.) is crucial for clean and fast type checking. Equally important is the robust handling of encountering a closing bracket when the stack is empty (e.g., `')abc'`). By popping `if stack else '#'`, we prevent an `IndexError` and introduce a sentinel value (`'#'`) that will never validly match an opening bracket, ensuring such cases correctly return `False`.
- **Final Stack State as Validity Indicator:** The elegance culminates in the final check: `return not stack`. If the stack is empty after iterating through the entire string, it signifies that every opening bracket found its proper, corresponding closing bracket. A non-empty stack, conversely, indicates unclosed brackets (e.g., `"((("`) or mismatched pairs where an invalid sequence led to an imbalance, providing a concise ultimate verdict.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(n)
Topics
This problem involves: String, Stack.
Companies
Asked at: Accenture, Accolite, Adobe, Agoda, Airbnb, Amazon, Anduril, Apple, Autodesk, Bank of America, Barclays, BlackRock, Bloomberg, Bolt, Booking.com, Braze, Capital One, Cisco, Cognizant, Criteo, DE Shaw, Dell, Deloitte, Disney, EPAM Systems, Epic Systems, Expedia, FreshWorks, GE Healthcare, Goldman Sachs, Google, Grab, HCL, Huawei, IBM, Infosys, Intel, Intuit, J.P. Morgan, LinkedIn, Lucid, Mastercard, Meta, Microsoft, Millennium, Mitsogo, Morgan Stanley, Nagarro, Netflix, Nike, Nvidia, Odoo, Ozon, Palo Alto Networks, PayPal, Paytm, Publicis Sapient, Qualcomm, Roblox, SAP, SOTI, Salesforce, Samsung, ServiceNow, Shopee, Siemens, Splunk, Spotify, Squarespace, Swiggy, Tencent, Tesla, ThoughtWorks, TikTok, Tripadvisor, Turing, UBS, Uber, VK, Visa, Walmart Labs, Wipro, Wix, X, Yahoo, Yandex, Zenefits, Zillow, Zoho, eBay, opentext, persistent systems, tcs.