1.将递归转化为循环
比如:逆序打印链表
// 递归方式
void printList(Node head){
if(null != head){
printList(head.next);
System.out.print(head.val + " ");
}
}
// 循环方式
void printList(Node head){
if(null==head){
return;
}
Stack<Node> s=new Stack<>();
// 将链表中的结点保存在栈中
Node cur=head;
while(null!=cur){
s.push(cur);
cur=cur.next;
}
// 将栈中的元素出栈
while(!s.empty()){
System.out.print(s.pop().val+" ");
}
}
public void show3(ListNode head) {
if(head == null) {
return;
}
if(head.next == null) {
System.out.println(head.val);
return;
}
show3(head.next);
System.out.println(head.val);
}
public void show4() {
Stack<ListNode> stack = new Stack<>();
ListNode cur = head;
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
//依次出栈
while (!stack.empty()) {
ListNode tmp = stack.pop();
System.out.println(tmp.val);
}
}
2.括号匹配
(1)闭合顺序不对([)]
(2)左括号多了(()
(3)右括号多了())
结论:
1.当括号是匹配的时候,最终i遍历完了字符串,并且栈为空
2.遇到不匹配的就直接结束
3.当i遍历完了字符串,但是栈当中仍然有括号,则必定是左括号多了(肯定不匹配)
4.当栈空了,但是字符串还没有遍历完,则必定不匹配
思考:如何判断匹配
https://leetcode.cn/problems/valid-parentheses/description/
javaclass Solution { public boolean isValid(String s) { Stack<Character> stack=new Stack<>(); for(int i=0;i<s.length();i++){ char ch=s.charAt(i); if(ch=='('||ch=='['||ch=='{'){ //左括号入栈,因为左括号一定是符号最开始的部分 stack.push(ch); } else{//是右括号的情况 if(stack.empty()){ return false; } else{ char tmp=stack.peek(); if((tmp=='('&&ch==')')||(tmp=='['&&ch==']')||(tmp=='{'&&ch=='}')){ //括号匹配成功 stack.pop(); } else{ return false; } } } } if(!stack.empty()){ return false; } return true; } }
3.逆波兰表达式
java
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack=new Stack<>();
for(String s:tokens){
if(!isOpera(s)){
//数字:放入栈当中
stack.push(Integer.parseInt(s));//将字符串转成整数
}
else{
//弹出栈顶的两个元素
int num2=stack.pop();
int num1=stack.pop();
switch(s){
case "+":
stack.push(num1+num2);
break;
case "-":
stack.push(num1-num2);
break;
case "*":
stack.push(num1*num2);
break;
case "/":
stack.push(num1/num2);
break;
}
}
}
return stack.pop();
}
public boolean isOpera(String s){
if(s.equals("+")||s.equals("-")||s.equals("*")||s.equals("/")){
return true;
}
return false;
}
}
4.栈的压入、弹出序列
1)何时入栈---每次都入
2)什么时候出栈
栈不为空的时候并且栈顶元素和k下标的元素相同时可以出栈
栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)
java
import java.util.*;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
Stack<Integer> stack = new Stack<>();
int j = 0;//变量popA这个数组
for (int i = 0; i < pushA.length; i++) {
stack.push(pushA[i]);
while (!stack.empty() && j < popA.length
&& stack.peek() == popA[j]) {
stack.pop();
j++;
}
}
return stack.empty();
}
}
5.最小栈
java
import java.util.Stack;
class MinStack {
private Stack<Integer> stack ;
private Stack<Integer> minStack ;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int val) {
stack.push(val);
//第一次在最小栈当中存储元素
if(minStack.empty()) {
minStack.push(val);
}else {
if(val <= minStack.peek()) {
minStack.push(val);
}
}
}
public void pop() {
//栈为空 则不能进行弹出元素
if(stack.empty()) {
return;
}
int val = stack.pop();
if(val == minStack.peek()) {
minStack.pop();
}
}
//获取栈顶元素 和 最小栈没有关系
public int top() {
if(stack.empty()) {
return -1;
}
return stack.peek();
}
//获取元素 不是删除元素
public int getMin() {
return minStack.peek();
}
}
1.入栈操作 stack正常入栈minStack 每次入栈的元素要和栈顶元素比较,如果比minStack 栈顶元素小,就要入栈。第一次入栈的时候,两个栈 都要放元素
2.出栈操作
stack这个栈正常出栈,但是每次出栈的时候都要和最小栈的栈顶元素比较,如果一样,此时两个栈 都要出元素。