面试题 16.26. 计算器 & 739. 每日温度

本文介绍了两种解决算术表达式计算的方法,包括传统的双栈法和巧妙的女少口苗法。在女少口苗法中,通过在第一个数字前添加'+',并利用运算符划分数值,遇到减号时直接取反,乘除运算时调整数值顺序。此外,还讲解了使用单调栈解决每日气温问题,如何找到更高气温的等待天数。这两种解法展示了栈在处理计算和查找最值问题时的高效性。
摘要由CSDN通过智能技术生成

面试题 16.26. 计算器

给定一个包含正整数、加(+)、减(-)、乘(*)、除(/)的算数表达式(括号除外),计算其结果。

表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。

示例 1:

输入: “3+2*2”
输出: 7
示例 2:

输入: " 3/2 "
输出: 1
示例 3:

输入: " 3+5 / 2 "
输出: 5
说明:

你可以假设所给定的表达式都是有效的。
请不要使用内置的库函数 eval。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/calculator-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法:

法一:双栈传统做法

创建俩栈,分别存放字符串中的数字和运算符。
如果想从左到右顺着算,则遍历字符串需要从字符串末尾往前遍历(栈的先进后出原理),否则需要注意提取的内容。
代码不再做演示。

法二:女少 女少 口苗 法

这种解法有点巧妙,我是借鉴力扣上别人的解法的,他没怎么解释,我看过后摸索清楚了。


妙点:

  • 只需创建一个栈存储数值。
  • 在第一个数前添加 “+” 即: +3 - 2 * 2
  • 利用运算符划分单位或多位的数值
  • 遇到 “-” 取反值压栈

这是初始状态:
在这里插入图片描述


这是遇到 “*” 乘号 或 除号 的时候:
在这里插入图片描述


剩下的我在代码中解释了 ↓↓↓
还不懂的佳人们可以自己画图演示哈

class Solution {
public:
    int calculate(string s) {
      stack<int> st;

      int num = 0; //存储遇到下一个运算符前的数值
      char c = '+'; //默认第一个的数前是 + 号
      for(int i=0; i<=s.length(); i++){ // i == s.length()时不会报s[i]越界错误,因此时 s[i] == '\0'。
      //需要等于的原因是为了不要遗漏push最后一个值
        if(isdigit(s[i])){
          //遇到下一个运算符前,算出真实数值
          num = num*10 + (s[i] - '0'); 
        }
        else if(isspace(s[i])) continue; //处理空格情况
        else{
          // 此时的c其实是上一个运算符,并不是此次的运算符
          switch(c){
            case '+': st.push(num);break;
            case '-': st.push(-num);break; // 妙的一步,遇到减号直接取反
            case '*': {
              // st.top()的值其实是上次符号'x'的前一个值,把这个值与'x'的后一个值相乘后压栈
              num *= st.top(); st.pop();
              st.push(num);
              break;
            }
            case '/': {
              //同上,但需注意除数与被除数的顺序
              num = st.top() / num; st.pop();
              st.push(num);
              break;
            }
          }
          //遇到了运算符,终止首位*10的取值
          num = 0;
          //存储当前运算符
          c = s[i];
        }
      }

      //遍历栈计算最终值
      int res = 0;
      while(!st.empty()){
        //这里就体现出了负号取反的优势了
        res += st.top();
        st.pop();
      }

      return res;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

739. 每日温度

请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/daily-temperatures
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这是我第一次遇到单调栈解法的题目。
我的理解就是,栈底的值(下标)所对应原来数组中的值,在遍历当前元素之前,必是最大的。
因为要取下标差值,所以入栈的都是元素的下标值。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& T) {
      stack<int> st;
      int len = T.size();
      vector<int> res(len, 0);
      for(int i=0; i<len; i++){
      	//下面这步目的是为了保持栈顶下标原来的值始终是最大的
        while(!st.empty() && T[st.top()] < T[i]){
          int idx = st.top(); st.pop();
          res[idx] = i - idx; //取差值
        }
        st.push(i);
      }
      return res;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值