力扣刷题篇之栈与队列3

系列文章目录



前言

本系列是个人力扣刷题汇总,本文是栈与队列。刷题顺序按照[力扣刷题攻略] Re:从零开始的力扣刷题生活 - 力扣(LeetCode)


一、表达式求值

150. 逆波兰表达式求值 - 力扣(LeetCode)

方法一,用栈

把数字都入栈,遇到运算符号就弹出两数进行相应计算,

这里需要注意,如果是除法,先弹出来的数是除数,后弹出的才是被除数。

class Solution {
    public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList();
        for (String s : tokens) {
            if ("+".equals(s)) {       
                stack.push(stack.pop() + stack.pop());    
            } else if ("-".equals(s)) {
                stack.push(-stack.pop() + stack.pop());
            } else if ("*".equals(s)) {
                stack.push(stack.pop() * stack.pop());
            } else if ("/".equals(s)) {
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 / temp1);
            } else {
                stack.push(Integer.valueOf(s));
            }
        }
        return stack.pop();
    }
//     int pos = 0;

//     public int evalRPN(String[] tokens) {
//         this.pos = tokens.length - 1;
//         return eval(tokens);
//     }

//     public int eval(String[] tokens) {
//         String token = tokens[pos];
//         if (token.equals("*")) {
//             pos--;
//             return eval(tokens) * eval(tokens);
//         }
//         if (token.equals("+")) {
//             pos--;
//             return eval(tokens) + eval(tokens);
//         }
//         if (token.equals("/")) {
//             pos--;
//             int op = eval(tokens);
//             return eval(tokens) / op;
//         }
//         if (token.equals("-")) {
//             pos--;
//             int op = eval(tokens);
//             return eval(tokens) - op;
//         }
//         pos--;
//         return Integer.parseInt(token);
//     }
 }

方法二,用递归,有点不好理解。

通过递归的方式,从逆波兰表达式的最后一个元素开始,根据操作符进行相应的计算。在递归的过程中,通过不断改变 pos 指针的位置,实现对逆波兰表达式的深度优先遍历。

class Solution {
    int pos = 0;

    // 主函数,接受逆波兰表达式的字符串数组
    public int evalRPN(String[] tokens) {
        // 初始化位置指针
        this.pos = tokens.length - 1;
        // 调用递归函数进行表达式计算
        return eval(tokens);
    }

    // 递归函数,根据当前位置的操作符进行计算
    public int eval(String[] tokens) {
        // 获取当前位置的操作符或操作数
        String token = tokens[pos];
        
        // 根据操作符进行相应的计算
        if (token.equals("*")) {
            pos--;
            // 递归计算乘法操作
            return eval(tokens) * eval(tokens);
        }
        if (token.equals("+")) {
            pos--;
            // 递归计算加法操作
            return eval(tokens) + eval(tokens);
        }
        if (token.equals("/")) {
            pos--;
            // 递归计算除法操作
            int op = eval(tokens);
            return eval(tokens) / op;
        }
        if (token.equals("-")) {
            pos--;
            // 递归计算减法操作
            int op = eval(tokens);
            return eval(tokens) - op;
        }
        // 如果是操作数,将其转换为整数并返回
        pos--;
        return Integer.parseInt(token);
    }
}

224. 基本计算器 - 力扣(LeetCode)

 方法一,用栈

只有加减法,于是用sign代表正负,然后要正确处理多位数的情况以及有括号的情况。

class Solution {
    public int calculate(String s) {
        Stack<Integer> stack = new Stack<Integer>();
        // sign 代表正负
        int sign = 1, res = 0;
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char ch = s.charAt(i);
            if (Character.isDigit(ch)) {
                int cur = ch - '0';
                while (i + 1 < length && Character.isDigit(s.charAt(i + 1)))
                    cur = cur * 10 + s.charAt(++i) - '0';
                res = res + sign * cur;
            } else if (ch == '+') {
                sign = 1;
            } else if (ch == '-') {
                sign = -1;
            } else if (ch == '(') {
                stack.push(res);
                res = 0;
                stack.push(sign);
                sign = 1;
            } else if (ch == ')') {
                res = stack.pop() * res + stack.pop();
            }
        }
        return res;
    }
}

方法二、 递归,回溯

使用回溯法,递归地解析并计算表达式。它从左到右遍历输入字符串,根据不同的字符类型执行不同的操作。

class Solution {
   
    public int calculate(String s) {
        char[] cs = s.toCharArray();
        this.len = cs.length;
        // 调用回溯函数,从字符串的第一个字符开始计算
        return backTrack(cs, 0)[0];
    }
    
    int len;  // 字符串长度

    // 回溯函数,用于解析并计算表达式
    // 返回数组,元素1表示区间和,元素2表示区间的右边界
    public int[] backTrack(char[] cs, int p) {
        char c = ' ';
        char op = '+';  // 初始操作符设为'+'
        int res = 0;    // 初始结果为0
        int num = 0;    // 用于记录当前数字的值

        for (int i = p; i < len; ++i) {
            c = cs[i];
            
            // 如果字符是数字,则更新num
            if (c >= '0' && c <= '9') {
                num = num * 10 + c - '0';
            } else if (c == '+' || c == '-') {
                // 如果字符是'+'或'-',更新结果和操作符,并将num清零
                res = (op == '+') ? res + num : res - num;
                op = c;
                num = 0;
            } else if (c == '(') {
                // 如果字符是'(',递归调用回溯函数处理括号内的表达式
                int[] sub = backTrack(cs, i + 1);
                num = sub[0];
                // 更新边界
                i = sub[1];
            } else if (c == ')') {
                // 如果字符是')',返回当前结果和右边界
                res = (op == '+') ? res + num : res - num;
                return new int[]{res, i};
            }
        }
        
        // 处理最后一个数字
        res = (op == '+') ? res + num : res - num;
        return new int[]{res, len};
    }
}

227. 基本计算器 II - 力扣(LeetCode)

 

 这个地方要说一下,

Deque(双端队列)和 Stack 都可以用来实现栈的功能。在 Java 中,Deque 接口提供了用于栈操作的方法,同时也提供了队列的操作。Stack 类则是 Vector 类的一个子类,专门用于实现栈。

推荐使用 Deque,因为它提供了更丰富的方法,而 Stack 则是基于 Vector,使用时需要注意线程安全性。Deque 在 Java 中自 Java 6 引入,并在 Java 7 中进行了进一步的优化。

看回这个题,方法一,用栈

class Solution {
    public int calculate(String s) {
        // 保存上一个符号,初始为 +
        char sign = '+';
        Stack<Integer> numStack = new Stack<>();
        // 保存当前数字,如:12是两个字符,需要进位累加
        int num = 0;
        int result = 0;
        for(int i = 0; i < s.length(); i++){
            char cur = s.charAt(i);
            if(cur >= '0'){
                // 记录当前数字。先减,防溢出
                num = num*10 - '0' + cur;
            }
            if((cur < '0' && cur !=' ' )|| i == s.length()-1){
                // 判断上一个符号是什么
                switch(sign){
                    // 当前符号前的数字直接压栈
                    case '+': numStack.push(num);break;
                    // 当前符号前的数字取反压栈
                    case '-': numStack.push(-num);break;
                    // 数字栈栈顶数字出栈,与当前符号前的数字相乘,结果值压栈
                    case '*': numStack.push(numStack.pop()*num);break;
                    // 数字栈栈顶数字出栈,除于当前符号前的数字,结果值压栈
                    case '/': numStack.push(numStack.pop()/num);break;
                }
                // 记录当前符号
                sign = cur;
                // 数字清零
                num = 0;
            }
        }
        // 将栈内剩余数字累加,即为结果
        while(!numStack.isEmpty()){
            result += numStack.pop();
        }
        return result;
    }
}

方法二、

class Solution {
    public int calculate(String s) {
        int[] oprands = new int[4];
        calculate(oprands, 0, '+');
        int num = 0;
        for(char c:s.toCharArray()){
            switch(c){
            case '+':
            case '-':
            case '*':
            case '/':
                calculate(oprands, num, c); num = 0; break;
            default:
                if ('0'<=c && c<='9'){
                    num = num*10 + c -'0';
                }
            }
        }
        calculate(oprands, num, '+');
        calculate(oprands, 0, '+');
        return oprands[0];
    }

    //0*1+ 2+
    //1-2* 2* -7+0+ 0+
    //1*2* 2-
    //1*2- 2*
    //

    //0+1-
    //0123
    private void calculate(int[] oprands, int num, int op){
        if (oprands[3]=='*'){
            oprands[2] *= num;
        }else if (oprands[3]=='/'){
            oprands[2] /= num;
        }else{
            switch(oprands[1]){
            case '+':
                oprands[0] += oprands[2]; break;
            case '-':
                oprands[0] -= oprands[2]; break;
            case '*':
                oprands[0] *= oprands[2]; break;
            case '/':
                oprands[0] /= oprands[2]; break;
            }
            oprands[1] = oprands[3];
            oprands[2] = num;
        }
        oprands[3] = op;
    }
}

772. 基本计算器 III - 力扣(LeetCode)

会员题,之后做

770. 基本计算器 IV - 力扣(LeetCode)

class Solution {
    private HashMap<String, Integer> map;
    private Deque<List<Item>> numbers;
    private Deque<Character> operators;
    private int index, size;

    public List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {
        map = new HashMap<>();
        for (int i = 0; i < evalvars.length; i++) {
            map.put(evalvars[i], evalints[i]);
        }
        numbers = new ArrayDeque<>();
        operators = new ArrayDeque<>();
        index = 0;
        size = expression.length();
        List<Item> items = calculate(expression);
        List<String> list = new ArrayList<>();
        for (Item item : items) {
            list.add(item.toString());
        }
        return list;
    }

    List<Item> calculate(String expression) {
        while (index < size) {
            char c = expression.charAt(index++);
            if (c == ' ') {
                continue;
            } else if (Character.isDigit(c)) {
                List<Item> list = new ArrayList<>();
                addList(list, getDigit(expression, c), new ArrayList<>());
                numbers.addLast(list);
            } else if (Character.isLowerCase(c)) {
                addListByName(expression, c);
            } else if (c == '(') {
                operators.addLast(c);
            } else {
                if (c == '*') {
                    if (!operators.isEmpty() && operators.peekLast() == '*') {
                        computeOnce();
                    }
                    operators.addLast(c);
                } else {
                    while (!operators.isEmpty() && operators.peekLast() != '(') {
                        computeOnce();
                    }
                    if (c == ')') {
                        operators.pollLast();
                    } else {
                        operators.addLast(c);
                    }
                }
            }
        }
        while (!operators.isEmpty()) {
            computeOnce();
        }
        return numbers.peek();
    }

    void computeOnce() {
        char operator = operators.pollLast();
        List<Item> items2 = numbers.pollLast();
        List<Item> items1 = numbers.pollLast();
        if (operator == '+') {
            numbers.addLast(add(items1, items2));
        } else if (operator == '-') {
            numbers.addLast(subtract(items1, items2));
        } else {
            numbers.addLast(multiply(items1, items2));
        }
    }

    void addListByName(String expression, char c) {
        List<Item> list = new ArrayList<>();
        String name = getName(expression, c);
        if (map.containsKey(name)) {
            addList(list, map.get(name), new ArrayList<>());
        } else {
            List<String> temp = new ArrayList<>();
            temp.add(name);
            list.add(new Item(1, temp));
        }
        numbers.addLast(list);
    }

    void addList(List<Item> list, int coef, List<String> vars) {
        if (coef != 0) {
            list.add(new Item(coef, vars));
        }
    }

    String getName(String expression, char c) {
        StringBuilder sb = new StringBuilder().append(c);
        while (index < size) {
            c = expression.charAt(index);
            if (!Character.isLowerCase(c)) {
                break;
            }
            sb.append(c);
            index++;
        }
        return sb.toString();
    }

    int getDigit(String expression, char c) {
        int digit = c - '0';
        while (index < size) {
            c = expression.charAt(index);
            if (!Character.isDigit(c)) {
                break;
            }
            digit = 10 * digit + c - '0';
            index++;
        }
        return digit;
    }

    List<Item> add(List<Item> items1, List<Item> items2) {
        List<Item> list = new ArrayList<>();
        int size1 = items1.size(), size2 = items2.size();
        for (int i = 0, j = 0; i < size1 || j < size2; ) {
            if (i == size1) {
                list.add(items2.get(j++));
            } else if (j == size2) {
                list.add(items1.get(i++));
            } else {
                Item item1 = items1.get(i), item2 = items2.get(j);
                int diff = item1.compareTo(item2);
                if (diff == 0) {
                    addList(list, item1.coef + item2.coef, item1.vars);
                    i++;
                    j++;
                } else if (diff > 0) {
                    list.add(item1);
                    i++;
                } else {
                    list.add(item2);
                    j++;
                }
            }
        }
        return list;
    }

    List<Item> subtract(List<Item> items1, List<Item> items2) {
        for (Item item : items2) {
            item.coef = -item.coef;
        }
        return add(items1, items2);
    }

    List<Item> multiply(List<Item> items1, List<Item> items2) {
        List<Item> list = new ArrayList<>();
        for (Item item1 : items1) {
            List<Item> items = new ArrayList<>();
            for (Item item2 : items2) {
                items.add(item1.multiply(item2));
            }
            list = add(list, items);
        }
        return list;
    }

    static class Item {
        int coef;
        List<String> vars;

        public Item(int coef, List<String> vars) {
            this.coef = coef;
            this.vars = vars;
        }

        Item multiply(Item item) {
            List<String> temp = new ArrayList<>();
            temp.addAll(vars);
            temp.addAll(item.vars);
            Collections.sort(temp);
            Item product = new Item(coef * item.coef, temp);
            return product;
        }

        int compareTo(Item item) {
            int diff = vars.size() - item.vars.size();
            if (diff != 0) {
                return diff;
            }
            List<String> temp = item.vars;
            for (int i = 0; i < vars.size(); i++) {
                diff = temp.get(i).compareTo(vars.get(i));
                if (diff != 0) {
                    break;
                }
            }
            return diff;
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append(coef);
            for (String name : vars) {
                builder.append('*').append(name);
            }
            return builder.toString();
        }
    }
}

二、用栈访问最后若干元素

三、递归

四、滑动窗口最大值问题

五、求前 K 个高频元素


总结

今天先写这点题吧,明天修改

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/148816.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Harmony SDK API 版本 与 Harmony OS 版本对照表,及如何查看鸿蒙手机Harmony SDK Api 版本

Harmony SDK API 版本 与 Harmony OS 版本对照表 Harmony OSHarmony SDK APIHarmony 4.09Harmony 3.19Harmony 3.08Harmony 3.0 pre7Harmony 2.2.06Harmony 2.1.05Harmony 2.04 具体到真机上可能会有差异&#xff0c;如我的手机OS版本是2.0&#xff0c;按照上面表应该是4&…

[NSSRound#7 Team]ShadowFlag

文章目录 前置知识/proc目录python的反弹shellpin码计算 解题步骤 前置知识 /proc目录 Linux系统上的/proc目录是一种文件系统&#xff0c;用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息&#xff0c;甚至可以通过更改其中某些文件来改变内核的运行状态。/pro…

机器学习中的偏差漂移:挑战与缓解

一、介绍 机器学习算法已在各个行业得到广泛采用&#xff0c;在自动化流程、制定数据驱动决策和提高效率方面发挥着关键作用。然而&#xff0c;他们也面临着挑战&#xff0c;其中一个重要的问题是偏见。机器学习模型中的偏差可能会导致不公平和歧视性的结果&#xff0c;并对现实…

华为云优惠券介绍、领取入口及使用教程

华为云是华为的云服务品牌&#xff0c;致力于为用户提供一站式云计算基础设施服务。为了吸引用户&#xff0c;华为云经常推出各种优惠活动&#xff0c;其中就包括优惠券的发放&#xff0c;下面将为大家详细介绍华为云优惠券的作用、领取入口以及使用教程。 一、华为云优惠券介绍…

数据分析场景下,企业如何做好大模型选型和落地?

在数据驱动的数字化时代&#xff0c;有效的数据分析已成为企业成功的关键因素。而随着大模型带来能力突破&#xff0c;让AI与数据分析相互结合&#xff0c;使分析结果更好支撑业务&#xff0c;促进企业内部数据价值释放&#xff0c;成为了当下企业用户尤为关注的话题。 如何按照…

微信小程序项目——基本目录构成

基本构成 pages 用来存放所有小程序的页面&#xff1b;utils 用来存放工具性质的模块&#xff08;比如&#xff1a;格式化时间的自定义模块&#xff09;&#xff1b;app.js 小程序项目的入口文件&#xff1b;app.json小程序项目的全局配置文件&#xff1b;app.wxss 小程序项目…

黑马程序员微服务第四天课程 分布式搜索引擎1

分布式搜索引擎01 – elasticsearch基础 0.学习目标 1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 例如&#xff1a; …

Bobo Python 学习笔记

安装 Bobo 可以通过通常的方式安装&#xff0c;包括使用setup.py install 命令。当然&#xff0c;您可以使用Easy Install、Buildout或pip。 安装bobo Collecting boboDownloading bobo-2.4.0.tar.gz (17 kB) Collecting WebObDownloading WebOb-1.8.7-py2.py3-none-any.whl…

如何搭建属于自己的AI数字人直播SAAS系统?

随着人工智能技术的不断发展&#xff0c;AI数字人直播正成为互联网行业的新宠。面向未来的AI数字人直播系统无疑是直播领域的新风口。虽然拥有众多优势&#xff0c;但从0到1搭建这个系统可能存在着资源、技术和时间的挑战。那么&#xff0c;如何可以快速搭建属于自己的AI数字人…

infercnv

文章目录 brief安装使用体验输入文件制作运行试试吧结果部分others brief InferCNV is used to explore tumor single cell RNA-Seq data to identify evidence for somatic large-scale chromosomal copy number alterations, such as gains or deletions of entire chromoso…

老师的保命大法

数字化高度发达的今天&#xff0c;成绩查询系统已经成为学校教育中不可或缺的一部分。不同于传统的成绩公布方式&#xff0c;成绩查询系统更加高效、便捷&#xff0c;同时也充分保障了每位学生的隐私&#xff0c;今天就来揭秘这个教师保命大法&#xff01; 1、代码查询法 对于…

视频集中存储/云存储平台EasyCVR级联下级平台的详细步骤

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

『亚马逊云科技产品测评』活动征文|阿里云服务器亚马逊服务器综合评测

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 文章目录 引言一、亚马逊&阿里云发展历史介绍1.1 亚马逊发展历史1.2…

wps卸载和重新安装

卸载WPS sudo apt remove wps-office安装WPS 下载地址 安装命令 sudo dpkg -i wps-office_11.1.0.11708_amd64.debsunyuhuasunyuhua-HKF-WXX:~$ sudo dpkg -i wps-office_11.1.0.11708_amd64.deb 正在选中未选择的软件包 wps-office。 (正在读取数据库 ... 系统当前共安装…

Linux安装jdk1.8教程(服务器可以访问网络)

文章目录 前言创建安装目录查看是否安装过下载解压配置环境变量查看是否安装成功 前言 本教程介绍了一种快捷的jdk1.8安装方法。 创建安装目录 mkdir -p /opt/software // 这是我自己的安装目录&#xff0c;根据自己的习惯确定查看是否安装过 rpm -qa | grep -i jdk需要注意…

达梦集群搭建

一、数据库安装 ###&#xff08;一&#xff09;安装前准备 版本准备 [rootlocalhost ~]# uname -a Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux将镜像文件传到/opt目录下 [rootlocalhost100 …

【软考】系统集成项目管理工程师【总】

引言 本来整理这篇文章的目的是方便自己23年考试用的 效果不错 目标完成。 接下来的目标是把这篇文章 做成参加该软考 小伙伴的唯一参考资料&#xff08;有它就够了&#xff09;来持续更新。。。 这篇文章我将当作一个长周期&#xff08;以年为单位&#xff09;项目运维起来&am…

二维码在区域巡查中的应用:隐患上报、巡逻巡更、管线巡查

针对管理制度不健全、维修不及时、纸质表格容易丢失等问题&#xff0c;可以在草料上搭建区域巡查二维码系统。通过组合功能模块的方式&#xff0c;实现扫码记录巡查情况、上报隐患和整改信息、发现异常问题后及时反馈给相关负责人等功能。 比如上海延吉物业管理有限公司搭建的…

vue2+antd——实现权限管理——js数据格式处理(回显+数据结构渲染)

vue2antd——实现权限管理——js数据格式处理 效果图如下&#xff1a;1.需求说明2.如何展开所有子项及孙子项目——在弹窗之前就获取树形结构&#xff0c;然后直接将数据传到弹窗中3.template部分代码4.script的data部分5.权限tree数据处理——将row中的权限分配到具体的value参…

Mysql MHA

MHA概述 MHA(MasterHigh Availability) 基于主库的高可用环境下&#xff0c;可以实现主从复制、故障切换&#xff1b; 主从的架构&#xff0c;最少需要一主两从。 作用 解决Mysql的单点故障问题&#xff0c;一旦主库崩溃&#xff0c;MHA可以在0-30s内自动完成故障切换。 原理…