首页 > 编程语言 > 详细

「Leetcode-算法_MId1006」从单栈到双栈

时间:2021-04-01 18:34:04      阅读:24      评论:0      收藏:0      [点我收藏+]

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

代码实现

class Solution {
    public int clumsy(int N) {
        // 先乘除 后加减
        
        // 标识
        int temp , result = 0;
        Deque<Integer> stack = new LinkedList<>();

        while (N > 0) {
            
            // 矫正 4 + 1
            if (N > 1) {
                temp = multiplication(N, --N);
            } else {
                temp = N;
            }

            // 作除法
            if (N > 1) {
                stack.offerLast(divsion(temp, --N));
            } else{
                stack.offerLast(temp);
                break;
            }

            if (N > 1) {
                stack.offerLast(--N);
            } else{
                break;
            }
            
            // 后移移位 防止 下一位出错 因为下一位可能进行乘法
            --N;
        }

        while (stack.size() > 1) {
            stackPlus(1, stack);

            if (stack.size() > 1) {
                stackPlus(-1, stack);
            }
        }

        return stack.pollFirst();
    }

    private int multiplication(int a, int b) {
        return a * b;
    }

    private int divsion(int a, int b) {
        return Math.floorDiv(a, b);
    }

    private void stackPlus(int sign, Deque<Integer> stack) {
        stack.offerFirst(stack.pollFirst() + stack.pollFirst() * sign);
    }
}

算法分析

时间复杂度: O(n)

空间复杂度: O(1)

通用计算器

维护双栈

知识栈:

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

  • Deque 双端队列接口

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

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

记录在这里的一处踩坑:

  • calculate() 中 一开始为了减少局部变量的使用 直接用deq.pollLast() 导致减法、除法运算时逻辑上的错误
class Solution {
    // 计算器
    public int clumsy(int N) {
        Deque<Integer> numDeq = new LinkedList();
        Deque<Character> operatorDeq = new LinkedList();
        // 操作符优先级
        Map<Character,Integer> priorityMap = new HashMap<>(){
            {
                put(‘*‘,2);
                put(‘/‘,2);
                put(‘-‘,1);
                put(‘+‘,1);
            }
        };
        char[] operators = new char[]{‘*‘,‘/‘,‘+‘,‘-‘};
        
        for (int i = N, index = 0; i > 0 ; --i, ++index) {
            // 数字直接入栈
            numDeq.offerLast(i);
            // 取对应操作符
            char operator = operators[index % 4];
            
            // 操作符栈不为空 且 栈内元素优先级都 高于 当前将入栈的操作符 ——》 计算栈内所有可以计算的
            while (!operatorDeq.isEmpty() && priorityMap.get(operatorDeq.peekLast()) >= priorityMap.get(operator)) {
                calculate(numDeq, operatorDeq);
            }

            // 操作符入栈
            operatorDeq.offerLast(operator);
        }

        // 由于最后一个操作符没必要入栈 所以 取出
        operatorDeq.pollLast();
        while (!operatorDeq.isEmpty()) {
            calculate(numDeq, operatorDeq);
        }
        return numDeq.peekLast();
    }

    // 计算函数-->取出 N 栈底两个元素 与 O 栈一个元素去运算;
    private void calculate(Deque<Integer> numDeq, Deque<Character> operatorDeq) {
        // 这里一定要把 两个都取出来 不然不能算减法和除法
        int addtion = 0 , a = numDeq.pollLast() , b = numDeq.pollLast();
        switch (operatorDeq.pollLast()){
            case ‘+‘ : addtion = a + b;break;
            case ‘-‘ : addtion = b - a;break;
            case ‘*‘ : addtion = a * b;break;
            case ‘/‘ : addtion = Math.floorDiv(b , a);break;
        }
        numDeq.offerLast(addtion);
    }

}

双栈的图示

N=3 index=2

技术分享图片

N = 3 index = 3

技术分享图片

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

战报

技术分享图片

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

「Leetcode-算法_MId1006」从单栈到双栈

原文:https://www.cnblogs.com/evlic/p/14606649.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!