Mid 1006 笨阶乘 栈/后缀

运算优化 + 栈

思路描述

每四个数一组

这四个数中前三个会进行乘、除 然后与最后一个相加

Stack 入前三个之和 与 最后一个数

4 举例

运算式 4 * 3 / 2 + 1 --> (4 * 3 / 2) + 1

temp 代表括号内元素运算值

plus 代表括号后元素运算值

循环入队 tempplus

循环运算 temp + plus - temp + plus

stack.size() == 1 时 返回结果

数据运算过程

测试 5
  • 5 * 4 / 3 + 2 -1

    • temp

      • 20
      • 6
    • plus
      • 2
    • 再处理
    • temp
      • 1
    • stack
      • 6 2 1

测试 6

  • 6 * 5 / 4 + 3 - 2 * 1

    • temp

      • 30
      • 7
    • plus
      • 3
    • 再处理
    • temp
      • 2
    • plus
      • null
    • stack
      • 7 3 2

代码实现

  1. class Solution {
  2. public int clumsy(int N) {
  3. // 先乘除 后加减
  4. // 标识
  5. int temp , result = 0;
  6. Deque<Integer> stack = new LinkedList<>();
  7. while (N > 0) {
  8. // 矫正 4 + 1
  9. if (N > 1) {
  10. temp = multiplication(N, --N);
  11. } else {
  12. temp = N;
  13. }
  14. // 作除法
  15. if (N > 1) {
  16. stack.offerLast(divsion(temp, --N));
  17. } else{
  18. stack.offerLast(temp);
  19. break;
  20. }
  21. if (N > 1) {
  22. stack.offerLast(--N);
  23. } else{
  24. break;
  25. }
  26. // 后移移位 防止 下一位出错 因为下一位可能进行乘法
  27. --N;
  28. }
  29. while (stack.size() > 1) {
  30. stackPlus(1, stack);
  31. if (stack.size() > 1) {
  32. stackPlus(-1, stack);
  33. }
  34. }
  35. return stack.pollFirst();
  36. }
  37. private int multiplication(int a, int b) {
  38. return a * b;
  39. }
  40. private int divsion(int a, int b) {
  41. return Math.floorDiv(a, b);
  42. }
  43. private void stackPlus(int sign, Deque<Integer> stack) {
  44. stack.offerFirst(stack.pollFirst() + stack.pollFirst() * sign);
  45. }
  46. }

算法分析

时间复杂度: O(n)

空间复杂度: O(1)

通用计算器

维护双栈

知识栈:

  • 后缀表达式(逆波兰式)

  • Deque 双端队列接口

    • 作用
      ll/add 添加元素
      fer/remove 删除元素
      ek/get 读取元素

      支持 语法 + First/Last 对头、尾 实现双向操作

记录在这里的一处踩坑:

  • calculate() 中 一开始为了减少局部变量的使用 直接用deq.pollLast() 导致减法、除法运算时逻辑上的错误
  1. class Solution {
  2. // 计算器
  3. public int clumsy(int N) {
  4. Deque<Integer> numDeq = new LinkedList();
  5. Deque<Character> operatorDeq = new LinkedList();
  6. // 操作符优先级
  7. Map<Character,Integer> priorityMap = new HashMap<>(){
  8. {
  9. put('*',2);
  10. put('/',2);
  11. put('-',1);
  12. put('+',1);
  13. }
  14. };
  15. char[] operators = new char[]{'*','/','+','-'};
  16. for (int i = N, index = 0; i > 0 ; --i, ++index) {
  17. // 数字直接入栈
  18. numDeq.offerLast(i);
  19. // 取对应操作符
  20. char operator = operators[index % 4];
  21. // 操作符栈不为空 且 栈内元素优先级都 高于 当前将入栈的操作符 ——》 计算栈内所有可以计算的
  22. while (!operatorDeq.isEmpty() && priorityMap.get(operatorDeq.peekLast()) >= priorityMap.get(operator)) {
  23. calculate(numDeq, operatorDeq);
  24. }
  25. // 操作符入栈
  26. operatorDeq.offerLast(operator);
  27. }
  28. // 由于最后一个操作符没必要入栈 所以 取出
  29. operatorDeq.pollLast();
  30. while (!operatorDeq.isEmpty()) {
  31. calculate(numDeq, operatorDeq);
  32. }
  33. return numDeq.peekLast();
  34. }
  35. // 计算函数-->取出 N 栈底两个元素 与 O 栈一个元素去运算;
  36. private void calculate(Deque<Integer> numDeq, Deque<Character> operatorDeq) {
  37. // 这里一定要把 两个都取出来 不然不能算减法和除法
  38. int addtion = 0 , a = numDeq.pollLast() , b = numDeq.pollLast();
  39. switch (operatorDeq.pollLast()){
  40. case '+' : addtion = a + b;break;
  41. case '-' : addtion = b - a;break;
  42. case '*' : addtion = a * b;break;
  43. case '/' : addtion = Math.floorDiv(b , a);break;
  44. }
  45. numDeq.offerLast(addtion);
  46. }
  47. }

双栈的图示

N=3 index=2

N = 3 index = 3

鸣谢:三叶姐姐的题解 双栈计算器是和这篇题解学的

战报

因为这道题的标签是 数学(找规律) , 排名不必过多在意

「Leetcode-算法_MId1006」从单栈到双栈的更多相关文章

  1. 算法总结之 在单链表和双链表中删除倒数第k个节点

    分别实现两个函数,一个可以删除单链表中倒数第k个节点,另一个可以删除双链表中倒数第k个节点 思路: 如果链表为空,或者k<1 参数无效 除此之外 让链表从头开始走到尾,每移动一步,就让k的值减1 ...

  2. 双栈(Dual Stack)

    参考博客: 双栈数据结构: https://blog.csdn.net/hebtu666/article/details/83011115 https://blog.csdn.net/cainv89/ ...

  3. LeetCode 1248. 统计「优美子数组」

    地址 https://www.acwing.com/solution/leetcode/content/5801/ 题目描述给你一个整数数组 nums 和一个整数 k. 如果某个子数组中恰好有 k 个 ...

  4. 字符串匹配「 KMP 算法 」

    引言 众所周知,字符串无论是在 OI 中还是别的计算机领域都占有比较大的比重,今天说的就是一个关于匹配字符串的算法——「 KMP 算法 」. 0x00 KMP 算法用于解决这样的一类问题:给定一个文本 ...

  5. leetcode算法学习----155. 最小栈(MinStack )

    下面题目是LeetCode算法155题: https://leetcode.com/problems/min-stack/ 题目1:最小函数min()栈 设计一个支持 push,pop,top 操作, ...

  6. ACM金牌选手讲解LeetCode算法《栈和队列的高级应用》

    大家好,我是编程熊,双非逆袭选手,字节跳动.旷视科技前员工,ACM金牌,保研985,<ACM金牌选手讲解LeetCode算法系列>作者. 上一篇文章讲解了<线性表>中的数组.链 ...

  7. 图解最长回文子串「Manacher 算法」,基础思路感性上的解析

    问题描述: 给你一个字符串 s,找到 s 中最长的回文子串. 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 「Ma ...

  8. 「算法笔记」快速数论变换(NTT)

    一.简介 前置知识:多项式乘法与 FFT. FFT 涉及大量 double 类型数据操作和 \(\sin,\cos\) 运算,会产生误差.快速数论变换(Number Theoretic Transfo ...

  9. 力扣Leetcode 1248. 统计「优美子数组」

    统计「优美子数组」 给你一个整数数组 nums 和一个整数 k. 如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」. 请返回这个数组中「优美子数组」的数目. 示例 ...

随机推荐

  1. CSS Grid Layout In Action

    CSS Grid Layout In Action CSS 异形网格布局实战 refs https://static-nginx-online.fbcontent.cn/tutor/tutor-ybc ...

  2. node cli & emoji

    node cli & emoji cli $ yarn add node-emoji $ npm i node-emoji https://github.com/omnidan/node-em ...

  3. TypedArray & buffer

    TypedArray & buffer https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Obj ...

  4. taro best practice

    taro best practice 最佳实践 https://taro-docs.jd.com/taro/docs/best-practice.html#关于-jsx-支持程度补充说明 https: ...

  5. DeFi 热潮下,NGK将成为下一个财富密码

    区块链正在脱虚向实,处于大规模落地,赋能实体产业的前夜,而在这个关键的关口,一个万亿市场的蓝海正在缓缓生成,成为区块链落地的急先锋,这个先锋便是DeFi. DeFi,即Decentralized Fi ...

  6. Python数据结构与算法_搜索插入位置(07)

    给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果目标值不存在于数组中,返回它将会被按顺序插入的位置. 你可以假设数组中无重复元素. 示例 1: 输入: [1,3,5,6], 5输出 ...

  7. 《进击吧!Blazor!》第一章 5.组件开发

    <进击吧!Blazor!>是本人与张善友老师合作的Blazor零基础入门系列视频,此系列能让一个从未接触过Blazor的程序员掌握开发Blazor应用的能力. 视频地址:https://s ...

  8. 一文读懂什么是kubernetes?

    kubernetes概述 kubernetes面世不过短短几年时间,kuberenetes已经成为容器编排领域事实上的标准,无论是公有云,私有云或混合云,kubernetes都将作为一个为任何应用,任 ...

  9. 基于Docker Compose部署分布式MinIO集群

    一.概述 Minio 是一个基于Go语言的对象存储服务.它实现了大部分亚马逊S3云存储服务接口,可以看做是是S3的开源版本,非常适合于存储大容量非结构化的数据,例如图片.视频.日志文件.备份数据和容器 ...

  10. if __name__ == '__main__':简单粗暴解释

    这个脚本被执行的时候,__name__ 值就是 __main__ ,才会执行 main()函数如果这个脚本是被 import 的话,__name__的值不一样.main()函数就不会被调用.这个句子用 ...