算法题型:栈(leetcode)

目录

一、150. 逆波兰表达式求值

二、71. 简化路径

三、20.题目要求:

四、剑指offer(5)

五、剑指offer(三)从尾到头打印链表


一、150. 逆波兰表达式求值
 

1.题目描述
评论 (114)
题解(20)New
提交记录
根据逆波兰表示法,求表达式的值。

有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:

整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:

输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: ((2 + 1) * 3) = 9
示例 2:

输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: (4 + (13 / 5)) = 6
示例 3:

输入: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
输出: 22
解释: 
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

2.分析:

(1)遇到数字先压栈

(2)一旦碰到符号,则出栈两个数,先出栈为b,后出栈为a(因为题目中“/”规定是前面的数除后面的数,所以我们统一用a/b比较直观),然后对a b进行相应的运算操作。
->这些操作都建立在题设:给定逆波兰表达式总是有效的

(3)将计算结果压栈,作为参数用于下一次计算

(4)最终栈内一定是只剩下一个数,这个数就是结果!

3.代码

class Solution {
     public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        int len = tokens.length;
        for (int i=0;i<len;i++){
            if (tokens[i].equals("+")||tokens[i].equals("-")
                    ||tokens[i].equals("*")||tokens[i].equals("/")){
                int b = stack.pop();
                int a = stack.pop();
                int res = 0;
                switch (tokens[i]){
                    case "+" : {res = a+b;break;}
                    case "-" : {res = a-b;break;}
                    case "*" : {res = a*b;break;}
                    case "/" : {res = a/b;break;}
                }
                stack.push(res);
            }
            else {
                stack.push(Integer.parseInt(tokens[i]));
            }
        }
        return stack.pop();
    }
}

二、71. 简化路径


1.题目描述
评论 (161)
题解(17)New
提交记录
以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径

请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。

 

示例 1:

输入:"/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。
示例 2:

输入:"/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
示例 3:

输入:"/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
示例 4:

输入:"/a/./b/../../c/"
输出:"/c"
示例 5:

输入:"/a/../../b/../c//.//"
输出:"/c"
示例 6:

输入:"/a//bc/d//././/.."
输出:"/a/b/c"

2.分析

(1)先将字符串拆分成字符串数组,使用String [] s = path.split("/");,以“/”作为拆分符号

->拆分后会产生字符串、空、“.”、“..”四种情况

(2)分类讨论
如果是 空 和 “.” 这两种情况,直接跳过;
如果是 “..” ,出栈一个字符串(即返回上一级的意思)
如果是 字符串 ,直接入栈。

(3)注意题目要求,最终栈内如果没有元素,我们返回“/”

(4)现在栈内顺序是相反的,我们使用StringBuffer 的 方法 str.insert(0,"/"+stack.pop());
出栈、并且存储最终结果!

3.代码

/**
 * IMUHERO
 * 2019/7/31
 */
package IMUHERO;

import java.util.Stack;

public class Solution71 {
    public String simplifyPath(String path) {
        String [] s = path.split("/");  //使用“/”分割,会产生字符串、空、“.”、“..”四种情况
        int len = s.length;
        Stack<String>stack = new Stack<>();
        for (int i=0;i<s.length;i++){
            if (s[i].equals("")||s[i].equals("."));//不做任何操作,直接i++;
            else if (s[i].equals("..")){
                if (!stack.isEmpty()){
                    stack.pop();
                }
            }
            else {
                stack.push(s[i]);//如果是字符串,直接压入栈
            }
        }

        if (stack.isEmpty())return "/";
        StringBuffer str = new StringBuffer();
        while (!stack.isEmpty()){
            str.insert(0,"/"+stack.pop());
        }
        return str.toString();
    }
}

三、20.题目要求:

1.题目描述:

Given a string containing just the characters '('')''{''}''[' and ']', determine if the input string is valid.

An input string is valid if:

  1. Open brackets must be closed by the same type of brackets.
  2. Open brackets must be closed in the correct order.

Note that an empty string is also considered valid.

二、题目分析:

1.使用栈的数据结构方式

2.先判断是否是‘(’  、‘[’、'{',是的话依次入栈,不是的话则pop栈内元素,判断是否匹配

3.注意所有输入元素结束后要判断栈内是否还有元素。

三、具体代码:

package IMUHERO;

import java.util.Stack;

class Solution {
    public boolean isValid(String s) {
        Stack<Character>stack=new Stack<>();
        for (int i=0;i<s.length();i++){
            char a=s.charAt(i);
            if (a=='('||a=='['||a=='{'){
                stack.push(a);
            }
            else {
                if (stack.isEmpty())return false;
                char topStack=stack.pop();
                if (a ==')' &&topStack!='(') return false;
                if (a ==']' &&topStack!='[') return false;
                if (a =='}' &&topStack!='{') return false;
            }
        }if (!stack.isEmpty())return false;else return true;
    }
}

main函数用于测试功能是否正确:

package IMUHERO;

public class main {
    public static void main (String[]args){
        Solution s=new Solution();
        System.out.println(s.isValid("()"));
        System.out.println(s.isValid( "()[]{}"));
        System.out.println(s.isValid("(]"));
        System.out.println(s.isValid("([)]"));
        System.out.println(s.isValid("{[]}"));
    }
}

result:

true
true
false
false
true

________________________________________________________

与leetcode上的结果相同:


四、剑指offer(5)

1.题目描述:

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

2.题目分析

1.队列是先进先出

2.栈是先进后出

3.push时先放进栈1,pop时先将栈1的元素压入栈2中,这样原本在栈1底下的元素就可以浮在栈2的上顶,这时直接pop栈2即可。

4.特别注意,在栈2的元素还没有完全pop出来时不要把栈1的元素压入栈2,否则先出来的元素又继续在栈2底下存放了。

3.具体代码

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    //int i=0;//i用来记录存入stack中元素的个数
    public void push(int node) {
        stack1.push(node);
       
    }
    
    public int pop() {
        if(!stack2.isEmpty())return stack2.pop();
        while(!stack1.isEmpty()){
            stack2.push(stack1.pop());
        }
            return stack2.pop();
    }
}

五、剑指offer(三)从尾到头打印链表

一、题目描述

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

二、题目分析

1.利用栈

2.利用ArrayList.add(0,int e),不断添加到第一个位置

3.利用链表递归

三、代码

1.方法一:栈

import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        Stack<Integer> temp = new Stack<>();
        ArrayList<Integer> newList = new ArrayList<>();
        ListNode t = listNode;
       
            while( t != null ){
                
                temp.push(t.val);
                t = t.next;
            }
            while( !temp.empty() ){
                newList.add(temp.pop());
            }
            return newList;
    }
}

2.方法二:ArrayList.add(0,int e)

import java.util.ArrayList;
 
     class ListNode {
         int val;
         ListNode next = null;
 
         ListNode(int val) {
             this.val = val;
         }
    }
 
 
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> arr=new ArrayList<>();
        ListNode cur=listNode;
        while(cur!=null){
            arr.add(0,cur.val);
            cur=cur.next;
        }
        return arr;
    }
 
}

3.方法三:递归

import java.util.ArrayList;
 
public class Solution {
    ArrayList<Integer> arr=new ArrayList<>();
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        print(listNode);
        return arr;
    }
    public void print(ListNode listNode){
        if(listNode==null)return;
        print(listNode.next);
        arr.add(listNode.val);
        return;
    }
    
 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
LeetCode是一个非常受欢迎的在线编程平台,提供了大量的算法目,涵盖了各种难度级别和题型。下面是一些常用的LeetCode算法: 1. 两数之和(Two Sum):给定一个整数数组和一个目标值,找出数组中和为目标值的两个数的索引。 2. 反转字符串(Reverse String):反转给定字符串中的字符顺序。 3. 最长公共前缀(Longest Common Prefix):找出一组字符串中最长的公共前缀。 4. 合并两个有序链表(Merge Two Sorted Lists):将两个有序链表合并为一个新的有序链表。 5. 有效的括号(Valid Parentheses):判断给定的字符串中的括号是否有效。 6. 盛最多水的容器(Container With Most Water):给定一组非负整数,表示一组垂直线在x轴上的坐标,找出两条线与x轴组成的容器可以容纳的最大水量。 7. 三数之和(3Sum):给定一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a + b + c = 0。 8. 最长回文子串(Longest Palindromic Substring):找出给定字符串中的最长回文子串。 9. 二叉树的最大深度(Maximum Depth of Binary Tree):计算二叉树的最大深度,即从根节点到最远叶子节点的最长路径上的节点数。 10. 两个排序数组的中位数(Median of Two Sorted Arrays):给定两个大小为m和n的有序数组,找出这两个数组合并后的中位数。 以上只是LeetCode中的一小部分常用算法目,LeetCode还有很多其他类型的目,包括动态规划、回溯、贪心算法等等。如果你有具体的算法或者需要更多的目推荐,请告诉我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMUHERO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值