【代码随想录】Day 11栈和队列Ⅱ(有效括号、字符串相邻重复项、逆波兰表达式)

第一题

力扣

学习记录:

将每一对有效的括号通过栈来排除:遇到左括号如"("、"["、"{"时入栈,遇到右括号")"、"]"、"}"时,检查栈顶元素是否是对应的左括号,如果是则出栈,否则返回`false`。最后,如果栈为空,返回`true`,否则返回`false`。

根据提示自己写的:

class Solution {
public:
    bool isValid(string s) {
        stack<char> words;
        if (s.size() % 2 == 1) return false;
        for (char c:s) {
            if ((c == '(' || c == '[' || c == '{'))  words.push(c);
            else {
                if (words.empty()) return false;
                else if (c == ')' && words.top() == '(') {
                   words.pop(); 
                }
                else if (c == ']' && words.top() == '[') {
                   words.pop(); 
                }
                else if (c == '}' && words.top() == '{') {
                   words.pop(); 
                }
                else return false;//避免跳过非匹配括号
            }
        }
        if (words.empty()) return true;
        else return false;
    }
};

代码随想录的:

class Solution {
public:
    bool isValid(string s) {
        if (s.size() % 2 != 0) return false; // 如果s的长度为奇数,一定不符合要求
        stack<char> st;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '(') st.push(')');
            else if (s[i] == '{') st.push('}');
            else if (s[i] == '[') st.push(']');
            // 第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号 return false
            // 第二种情况:遍历字符串匹配的过程中,发现栈里没有我们要匹配的字符。所以return false
            else if (st.empty() || st.top() != s[i]) return false;
            else st.pop(); // st.top() 与 s[i]相等,栈弹出元素
        }
        // 第一种情况:此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false,否则就return true
        return st.empty();
    }
};

第二题

力扣

自己写的老提示超出内存限制,明明和代码随想录的一模一样,我不懂为什么:

class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> words;
        for (auto c:s) {
            if (words.empty() || c != words.top()) words.push(c);
            else  words.pop();
        }
        string result="";
        while(!words.empty()) {
            result = result + words.top();
            words.pop();
        }
        reverse (result.begin(), result.end()); // 此时字符串需要反转一下
        return result;
    }
};

学习记录: 

看了力扣上别人的评论才知道问题出在result = result + words.top()上, 参考C#和C++字符串拼接的性能分析_c# tostring性能_Real_JumpChen的博客-CSDN博客

 所以能写str+='a'就写这个!

TIPS:

翻转函数:reverse(str.begin(), str.end())

定义size:str.resize()

此外string本身也可以当作栈使用:

class Solution {
public:
    string removeDuplicates(string S) {
        string result;
        for(char s : S) {
            if(result.empty() || result.back() != s) {
                result.push_back(s);
            }
            else {
                result.pop_back();
            }
        }
        return result;
    }
};

第三题 

力扣

学习记录:

逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面。

平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。

该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。

逆波兰表达式主要有以下两个优点:

  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。

  • 适合用栈操作运算:遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中。

自己采用switch经过GPT修改写的代码:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> num;
        for (auto c:tokens) {
            if (c == "+" || c == "-" || c == "*" || c == "/") {
                int res = num.top();
                num.pop();
                switch (c[0]) { //因为c是string类型,需要判断的符号又都是单符号,因此c[0]==char类型的+-*/
                    case '+': res = num.top() + res; break; //case后跟整数类型
                    case '-': res = num.top() - res; break;
                    case '*': res = num.top() * res; break;
                    case '/': res = num.top() / res; break;
                }
                num.pop();
                num.push(res);
            }
            else {
                num.push(stoi(c));
            }
        }
        return num.top();
    }
};

TIPS:

  1. 在每个 case 语句后面,需要使用 break 语句来结束当前的 case,否则会发生所谓的 “fallthrough”,即程序会继续执行下一个 case 语句,直到遇到 break 语句或者 switch 语句的结束;
  2. 在 switch 语句的后面应该使用大括号 {} 而不是冒号 :;
  3. `switch`语句在C++中只能用于整数类型(包括枚举类型)的变量或表达式,不可以直接用于字符串。

`c`在这里是一个`string`类型的变量。写`c[0]`其实是获取了这个字符串的第一个字符(`char`类型)。`char`类型在C++中被视为一种整数类型,所以可以在`switch`语句中使用它。例如,对于字符串`"+"`,`c[0]`就是字符`'+'`。因为所有的操作符都只有一个字符,所以使用`c[0]`是合适的。

代码随想录:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        // 力扣修改了后台测试数据,需要用longlong
        stack<long long> st; 
        for (int i = 0; i < tokens.size(); i++) {
            if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
                long long num1 = st.top();
                st.pop();
                long long num2 = st.top();
                st.pop();
                if (tokens[i] == "+") st.push(num2 + num1);
                if (tokens[i] == "-") st.push(num2 - num1);
                if (tokens[i] == "*") st.push(num2 * num1);
                if (tokens[i] == "/") st.push(num2 / num1);
            } else {
                st.push(stoll(tokens[i]));
            }
        }

        int result = st.top();
        st.pop(); // 把栈里最后一个元素弹出(其实不弹出也没事)
        return result;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值