Given a string s
containing just the characters '('
, ')'
, '{'
, '}'
, '['
and ']'
, determine if the input string is valid.
An input string is valid if:
Example 1:
Input: s = "()" Output: true
Example 2:
Input: s = "()[]{}" Output: true
Example 3:
Input: s = "(]" Output: false
Example 4:
Input: s = "([)]" Output: false
Example 5:
Input: s = "{[]}" Output: true
Constraints:
1 <= s.length <= 104
s
consists of parentheses only '()[]{}'
.The core challenge of this problem is to ensure that every opening bracket has a corresponding closing bracket and that they are correctly nested. This problem is significant in various applications such as parsing expressions in compilers, validating mathematical expressions, and ensuring the correctness of nested structures in code.
Potential pitfalls include mismatched brackets, incorrect nesting, and unbalanced brackets.
To solve this problem, we can use a stack data structure. The stack helps us keep track of the opening brackets, and we can easily match them with the corresponding closing brackets.
A naive solution might involve checking each bracket and trying to match it with the corresponding closing bracket. However, this approach is not optimal as it can lead to multiple passes over the string and complex logic to handle nesting.
The optimized solution involves using a stack to keep track of the opening brackets. As we iterate through the string, we push each opening bracket onto the stack. When we encounter a closing bracket, we check if it matches the top of the stack. If it does, we pop the stack; otherwise, the string is invalid.
#include <iostream>
#include <stack>
#include <unordered_map>
bool isValid(std::string s) {
std::stack<char> stack;
std::unordered_map<char, char> matchingBrackets = {
{')', '('},
{']', '['},
{'}', '{'}
};
for (char c : s) {
// If the character is a closing bracket
if (matchingBrackets.find(c) != matchingBrackets.end()) {
// Check if the stack is empty or the top of the stack does not match
if (stack.empty() || stack.top() != matchingBrackets[c]) {
return false;
}
stack.pop();
} else {
// If it's an opening bracket, push it onto the stack
stack.push(c);
}
}
// If the stack is empty, all brackets were matched correctly
return stack.empty();
}
int main() {
std::string s = "{[]}";
std::cout << (isValid(s) ? "true" : "false") << std::endl;
return 0;
}
The time complexity of this solution is O(n) because we process each character in the string exactly once. The space complexity is also O(n) in the worst case, where all characters are opening brackets and are pushed onto the stack.
Potential edge cases include:
To test the solution comprehensively, consider the following test cases:
Using a testing framework like Google Test can help automate and manage these test cases effectively.
When approaching such problems, consider using data structures like stacks that are well-suited for managing nested structures. Practice solving similar problems to develop a deeper understanding of common patterns and techniques.
Understanding and solving the valid parentheses problem is crucial for various applications in computer science. By using a stack, we can efficiently check for balanced and correctly nested brackets. Practice and familiarity with data structures will enhance your problem-solving skills.