1. 有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = “()”
输出:true
1.1 HashMap+栈
将左括号作为key,右括号作为value,然后存入map集合里面去,只有当当前字符是左括号时候,才会让其进入,否则就是右括号,然后将当前栈顶元素弹出,找到对应的右括号,然后比对两个括号是否一致。
public static boolean isValid(String s) {
if (s.length() <= 1) return false;
// 将左括号作为key,右括号作为value
HashMap<Character, Character> map = new HashMap<>();
map.put('{', '}');
map.put('[', ']');
map.put('(', ')');
// 栈记录左括号
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char currChar = s.charAt(i);
// 左括号
if (map.containsKey(currChar)) {
// 左括号入栈
stack.push(currChar);
} else {
// 右括号
if (!stack.isEmpty()) {
// 栈顶元素对应左括号
Character leftCharKey = stack.pop();
// 找到对应右括号
Character rightChar = map.get(leftCharKey);
// 右括号不等于当前括号
if (rightChar != currChar) {
return false;
}
// 栈为空,表示没左括号进入
} else {
return false;
}
}
}
return stack.isEmpty();
}
时间复杂度:O(n) 将字符串遍历找到左括号存入,而map的查找元素时间复杂度是O(1)
空间复杂度:map的空间复杂度是O(1),栈出去元素时间复杂度O(n/2),因为只是存入了左括号。
1.2 栈优化
可以看出,第一种方法主要是使用map来进行查找存储括号,但是由于题目已知相应的括号,那么可以稍微简化一下,我只需要判断当前字符是不是左括号,是左括号,然后将对应的右括号添加栈,如果是右括号,就比对当前括号是不是一致。
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i=0;i<s.length();i++){
char currChar = s.charAt(i);
if(currChar == '['){
stack.push(']');
}else if(currChar == '{'){
stack.push('}');
}else if(currChar == '('){
stack.push(')');
}else{
// 右括号
if(stack.isEmpty() || stack.pop() != currChar){
return false;
}
}
}
return stack.isEmpty();
}
不过这个方法只适用于少量数据括号,数据量多了,还是要使用map存储。
2. 最长有效括号
给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
输入:s = “(()”
输出:2
解释:最长有效括号子串是 “()”
2.1 栈
- 如果出现’(',保留当前下标
- 出现’)',先弹出栈顶元素,默认这两个括号是一对,此时长度就是右括号的下标减去左括号的下标
- 判断是否栈为空,为空就要把当前右括号重新放入栈里面,原因是没有找到匹配的左括号
public int longestValidParentheses(String s) {
Stack<Integer> stack = new Stack<>();
int maxLen =0;
stack.push(-1);
for(int i= 0;i<s.length();i++){
char currChar = s.charAt(i);
if(currChar == '(' ){
stack.push(i);
}else {
stack.pop();
if(stack.isEmpty() ){
stack.push(i);
}else{
maxLen = Math.max(maxLen,i-stack.peek());
}
}
}
return maxLen;
}
时间复杂度:O(n)
空间复杂度:O(n)
总结:这一题使用栈代码看起来简单,但是实际做的时候发现,比较难以考虑到一些边界值以及将下标放入栈里面去。
3. 类似题目
Leetcode20 有效的括号、LeetCode22 .括号生成、LeetCode32.最长有效括号、LeetCode301.删除无效的括号和leetcode 856 括号的分数等。
后面几题都涉及到了动态规划等等,之后再做。