笔记1 第一周 p2 栈,队列,表达式求值——有效的括号,最小栈,基本计算器——极客时间算法训练营

之前收藏了极客时间的算法训练营3期 共10周,计划每周内容分3p博客来记录学习,主要形式为

方法类型1

题1

题解

题2

题解

方法类型2

题1

题解

……

题目大体来自leetcode 和 acwing

主要记录和理解代码,所以基本完全搬运了视频题解代码,

个人学习感受体现在大致思路的总结和注释上。






20. 有效的括号

155. 最小栈

150. 逆波兰表达式求值

227. 基本计算器 II

224. 基本计算器

20. 有效的括号

class Solution {
public:
    bool isValid(string s) {
        for(char ch : s){
            if (ch == '(' || ch == '[' || ch == '{') s1.push(ch);//这三种情况会入栈
            else{//遇到不是左括号的情况返回false的情况更好讨论。
                if (s1.empty()) return false;
                if (ch == '}' && s1.top() != '{') return false;
                if (ch == ']' && s1.top() != '[') return false;
                if (ch == ')' && s1.top() != '(') return false;
                s1.pop();
            }
        }
        return s1.empty();//空了就对了,还有说明false;
    }
private:
    stack<char> s1;//第一次定义成了s,命名重复了;
};

155. 最小栈

直接调用了库来实现。

class MinStack {
public:
    MinStack() {

    }
    
    void push(int val) {
        s.push(val);//为了出栈方便,所以每个值都会计算之前的最小值入栈
        if (preMin.empty()) preMin.push(val);
        else preMin.push(min(preMin.top(), val));
    }
    
    void pop() {
        s.pop();//两个栈一样高;
        preMin.pop();
    }
    
    int top() {
        return s.top();
    }
    
    int getMin() {
        return preMin.top();
    }
private:
    stack<int> s;
    stack<int> preMin;
};


/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(val);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

150. 逆波兰表达式求值

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        for(string& token : tokens){
            if (token == "+" || token == "-" || token == "*" || token == "/"){
                    int y = s.top();//先出来的是第二个计算值
                    s.pop();
                    int x = s.top();
                    s.pop();
                    int z = calc(x, y, token);
                    s.push(z);//两个数字变一个入栈
                }else{
                    s.push(atoi(token.c_str()));//不是符号数字入栈
                }
            }
            return s.top();
        }
private:
   stack<int> s;
   int calc (int x, int y, string& op){
       if(op == "+") return x + y;
       if(op == "-") return x - y;
       if(op == "*") return x * y;
       if(op == "/") return x / y;
       return 0;
    }
};

227. 基本计算器 II

class Solution {
public:
    int calculate(string s) {
        s += ' ';//高效解决结尾数字无法判断的问题
        vector<string> tokens;
        string number = "";
        for(char ch : s){
            if(ch >= '0' && ch <= '9'){
                number += ch;//重载的+=,插入了字符到字符串中
                continue;
            }else{
                if(!number.empty()){//把字符串整个加入到vector里
                    tokens.push_back(number);
                    number = "";
                }
            }
            if(ch == ' ') continue;
            int currRank = getRank(ch);//判定当前符号的优先级
            while(!ops.empty() && currRank <= getRank(ops.top())){
                tokens.push_back(string(1, ops.top()));
                ops.pop();//符号栈顶优先级高时,先出符号栈进入vector
            }
            ops.push(ch);//出完了把当前符号入栈
        }
        while(!ops.empty()){//最后把所有符号栈剩余内容放到表达式里
            tokens.push_back(string(1,ops.top()));
            ops.pop();
        }
        return evalRPN(tokens);//逆波兰表达式求值
    }
private:
int evalRPN(vector<string>& tokens) {//逆波兰表达式求值
		for (string& token : tokens) {
			if (token == "+" || token == "-" || token == "*" || token == "/") {
				int y = s.top();
				s.pop();
				int x = s.top();
				s.pop();
				int z = calc(x, y, token);
				s.push(z);
			}
			else {
				s.push(atoi(token.c_str()));
			}
		}
		return s.top();
	}
stack<int> s;
	int calc(int x, int y, string& op) {
		if (op == "+") return x + y;
		if (op == "-") return x - y;
		if (op == "*") return x * y;
		if (op == "/") return x / y;
		return 0;
	}
stack<char> ops;
int getRank(char op){
    if(op == '+' || op == '-') return 1;
    if(op == '*' || op == '/') return 2;
    return 0;
}
};

224. 基本计算器

这里有类似 -3 +2的算式,可以用补0的方式,补成0-3+2

本题教学了根据不同情况补0的方式

class Solution {
public:
    int calculate(string s) {
        s += ' ';
        vector<string> token;//逆波兰表达式
        string number = "";
        bool needZero = true;//没有说明存在-当做负号,可
        //以在诸如-3 + 3这类算式前加0
        for(char ch : s){//大体同224题
            if(ch >= '0' && ch <= '9'){
                number += ch;
                needZero = false;//数字打头不用补0
                continue;
            }else{
                if(!number.empty()){
                    token.push_back(number);
                    number = "";
                }
            }
            if (ch == ' ') continue;
            if (ch == '(') {
                ops.push(ch);
                needZero = true;
                continue;//左括号直接入栈标记括号所在位置
            }
            if (ch == ')'){//遇到右括号,左括号之前的所有值计算
                while(ops.top() != '('){
                    token.push_back(string(1,ops.top()));
                    ops.pop();
                }
                ops.pop();//弹出左括号
                needZero = false;//右括号完成后肯定会入栈一个值,不用补0
                continue;
            }
            if(needZero == true && (ch == '-')){
                token.push_back("0");//减号不清楚是否是负号需要考虑补0
            }
            int currRank = getRank(ch);
            while(!ops.empty() && currRank <= getRank(ops.top())){
                token.push_back(string(1,ops.top()));
                ops.pop();
            }
            needZero = true;//计算完一串式子,新的表达式部分需要补0
            //也许有这种算式? 2 * 3 + 1 + -1
            ops.push(ch);
            }
        while (!ops.empty()){
            token.push_back(string(1,ops.top()));
            ops.pop();
        }
        return evalRPN(token);
    }
private:
    stack<char> ops;
    stack<int> num;
    int evalRPN(vector<string>& tokens){
        for(string& token : tokens){
            if(token == "+" || token == "*" || token == "-" || token == "/"){
                int y = num.top();
                num.pop();
                int x = num.top();
                num.pop();
                int z = calc(x, y, token);
                num.push(z);
            }else{
                num.push(atoi(token.c_str()));
            }
        }
        return num.top();
    }
    int calc(int x, int y, string token){
        if(token == "+") return x + y;
        if(token == "*") return x * y;
        if(token == "-") return x - y;
        if(token == "/") return x / y;
        return 0;
    }
    int getRank(char ops){
        if (ops == '+' || ops == '-') return 1;
        if (ops == '*' || ops == '/') return 2;
        return 0;
    }

};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值