目录
一、将递归转化为循环
逆序打印链表:
java
// 递归方式
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 + " ");
}
}
关于递归的思路,如下图所示:

而关于循环的思路,本质就是利用栈本身后进先出的特点:

二、括号匹配
OJ链接:
https://leetcode.cn/problems/valid-parentheses/description/

要想解决这道题 ,首先我们得明白括号所有的情况有哪些,有了思路,才能够较好地去写代码。

四种情况:
-
栈顶和当前i下标的括号不匹配--字符串没有遍历完&&栈中仍存在左括号--false
-
字符串便利完成&&栈中没有左括号--true
-
字符串便利完成&&(但是)栈中仍然存在左括号--false
4.字符串没有遍历完&&(但是)栈已经空了--false
++而解决这道题的关键思路是:++
将所有的左括号放入栈中,然后一个个取出来与没有放入栈中的右括号进行比较,倘若字符串遍历完并且栈已经为空后,那么代表括号匹配了,返回true,否则返回false
代码如下:
java
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
//1.遍历字符串
for(int i=0; i<s.length(); i++){
char ch = s.charAt(i);
//2.判断是左括号放到栈里面
if(ch == '(' || ch == '[' || ch == '{'){
stack.push(ch);
}else{
//3.他是右括号
//3.1 此时ch是右括号,但是栈是空的
if(stack.empty()){
return false;
}
//3.2此时栈不为空,所以取出栈顶元素进行判断
//3.2.1匹配
char ch2 = stack.peek(); //( { [
if(ch2 == '(' && ch == ')' || ch2 == '[' && ch == ']' || ch2 == '{' && ch == '}'){
stack.pop();
}else{
//3.2.2 不匹配
return false;
}
}
}
if(!stack.empty()){
return false;
}
return true;
}
}
三、栈的压入、弹出序列
来看题目:

如何思考这道题呢?来看下图:

如上图所示,我们有两个数组,一个pushV用来入栈,一个popV用来出栈
我们这样写代码:
pushV定义一个便利下标 i ,popV定义一个便利下标 j
先让 i 开始走,每走一个就压一个元素入栈,然后再与 popV中 j 下标的元素进行比较,
若相同,则弹出元素,并且让 j 这个下标++,如果顺利的话,当 i 遍历完 pushV.length 长度时,
此时若栈为空,说明此时的压入和弹出序列是匹配的。
PS:需要注意,在判断时 内层循环需要注意 stack 不能为空,这样是为了防止出现空指针异常。
同时也需要保证 j 下标不会越界。
++代码如下:++
java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pushV int整型一维数组
* @param popV int整型一维数组
* @return bool布尔型
*/
public boolean IsPopOrder (int[] pushV, int[] popV) {
Stack<Integer> stack = new Stack<>();
int j = 0;
for(int i=0; i<pushV.length; i++){
stack.push(pushV[i]);
while(!stack.empty() && j<popV.length && stack.peek() == popV[j]){
j++;
stack.pop();
}
}
return stack.empty();
}
}
四、逆波兰表达式求值
OJ链接:
https://leetcode.cn/problems/evaluate-reverse-polish-notation/

大家可以先自行去了解一下后缀表达式:
入栈与出栈。


++代码如下:++
java
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for(String str : tokens){
if(!isOperations(str)){
//是数字字符串
stack.push(Integer.parseInt(str));
}else{
//是运算符 + - * /
int val2 = stack.pop();
int val1 = stack.pop();
switch(str){
case "+":
stack.push(val1 + val2);
break;
case "-":
stack.push(val1 - val2);
break;
case "*":
stack.push(val1 * val2);
break;
case "/":
stack.push(val1 / val2);
break;
}
}
}
return stack.pop();
}
public boolean isOperations(String s){
if(s.equals("+") || s.equals("*") || s.equals("/") || s.equals("-")){
return true;
}
return false;
}
}
五、最小栈--以O(1)时间来获取到他的最小值
OJ链接:
https://leetcode.cn/problems/min-stack/


OJ模板:
java
class MinStack {
public MinStack() {
}
public void push(int val) {
}
public void pop() {
}
public int top() {
}
public int getMin() {
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
来看思路:题目规定了要在常数时间内检索到最小元素,
所以,我们这里有必要定义两个栈,一个普通栈,一个最小栈,用空间来换时间
++具体的思路可以这么来看:++一、入栈的过程当中:
- 每次存放元素的时候,都要和最小栈的栈顶元素进行比较
val ++<=++ minStack.peek()
特别注意,第一点是小于等于,等于的情况也需要考虑进去,因为假如有两个一样的最小值,那么根据下面出栈的原则,此时以常数时间取出最小值就会出问题
- 如果最小栈 第一次存放的时候 是空的 ,那么直接存储
二、出栈:
- 每次出栈的时候都要判断最小栈的栈顶元素,如果相同最小栈也得出栈
来看具体的代码实现:
java
class MinStack {
public Stack<Integer> stack;
public 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{
int topVal = minStack.peek();
//注意此处一定是<=,千万别漏了=号
if(val <= topVal){
minStack.push(val);
}
}
}
public void pop() {
int popVal = stack.pop();
if(popVal == minStack.peek()){
minStack.pop();
}
}
//相当于peek方法
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
PS:关于栈的实现--用链表:

由上图所示,我们之前讲的栈 是以 数组实现的栈,其实链表也可以实现栈;
我们也可以像下面的代码一样,用 LinkedList 来定义栈,LinkedList这个类 自己实现了push、pop等方法:
java
public static void main(String[] args) {
LinkedList<Integer> stack = new LinkedList<>();
stack.push(1);
}

