今天是栈的应用练习,通过这几题可以发现,栈非常适合“消消乐”类型的问题,消除相邻相同元素,因为栈能够记录当前元素的同时还能记录当前元素的上一个元素。
首先分析会出现几种不符合条件的情况-总共是三种,一种是左括号多余,一种是左右括号不匹配,还有一种是右括号多余。在这里,如果将所有括号全部压入栈中的话,通过弹出的括号来进行判断的话会比较复杂。这里有一种巧妙的办法,从左到右,遇到左括号时往栈中压入右括号,当遇到右括号时,弹出栈顶元素与其匹配,若是不匹配,则是属于情况二;若是匹配则弹出栈顶元素,继续匹配判断,直到遍历完所有括号;若最后栈不为空,则出现了括号多余的情况,若为空,则返回true;因为从左到右只会先是左括号再是右括号,若是一开始就是右括号,那这里就没有左括号能与其匹配,属于右括号多余的情况;
这里还有一种技巧,就是在遇到右括号时,正面需要判断是哪一种右括号,而且要判断是否匹配,写起来十分麻烦,这里先写出不符合条件不匹配的右括号的情况,剩下直接一个else即可包含所有需要讨论的正面匹配的情况。当遇到正面讨论情况比较多比较复杂的时候,从反面入手,反面条件就会比较少,讨论完反面条件后一个else即可包含所有正面条件。
class Solution {
public boolean isValid(String s) {
ArrayDeque<Character> stack=new ArrayDeque<>();
char[] arr=s.toCharArray();
for(int i=0;i<arr.length;i++){
if(arr[i]=='('){
stack.addFirst(')');
}else if(arr[i]=='{'){
stack.addFirst('}');
}else if(arr[i]=='['){
stack.addFirst(']');
}else if(stack.isEmpty()||arr[i]!=stack.peekFirst()){ //非常巧妙,反向讨论
return false; //正面右括号不好讨论时,讨论其反例
}else{
stack.removeFirst();
}
}
return stack.isEmpty();
}
}
这题和上一题括号匹配方法相同,将字符往栈中压入,再压入的时候判断当前元素与栈顶元素,若相同则将栈顶元素弹出,若不同则继续压入。最后剩下栈中的元素,将栈中元素弹出逆序输出即可。这里逆序输出也是一个小技巧,运用字符连接符“+”,将每一个弹出栈的元素放在字符串的前端。
class Solution {
public String removeDuplicates(String s) {
ArrayDeque<Character> stack=new ArrayDeque<>();
for(int i=0;i<s.length();i++){
if(!stack.isEmpty()&&s.charAt(i)==stack.peekFirst()){
stack.removeFirst();
}else{
stack.addFirst(s.charAt(i));
}
}
String str=""; //使用一个空字符串通过将栈顶元素连接起来返回
while(!stack.isEmpty()){
str=stack.removeFirst()+str;//这里栈顶元素放在字符串最前面
}
return str;
}
}
该题的思路就是遇到数字时将其压入栈中,遇到运算符号时,取出两个栈顶元素进行运算。相除和相减时要注意栈顶元素的顺序,后出栈的元素是除数和减数。
这里同样是一种讨论字符是否为数字的正面情况不好讨论,从反面入手的方法。
class Solution {
public int evalRPN(String[] tokens) {
ArrayDeque<Integer> stack=new ArrayDeque<>();
for(int i=0;i<tokens.length;i++){
if("+".equals(tokens[i])){//正面为数字时加入栈中不好写,反面条件较少,从反面写
stack.addFirst(stack.removeFirst()+stack.removeFirst());
}else if("-".equals(tokens[i])){
stack.addFirst(-(stack.removeFirst()-stack.removeFirst()));
}else if("*".equals(tokens[i])){
stack.addFirst(stack.removeFirst()*stack.removeFirst());
}else if("/".equals(tokens[i])){
int temp1=stack.removeFirst();
int temp2=stack.removeFirst();
stack.addFirst(temp2/temp1);
}else {
stack.addFirst(Integer.valueOf(tokens[i]));
}
}
return stack.removeFirst();
}
}