代码随想录算法训练营第十一天|20.有效的括号、1047.删除字符串中的所有相邻重复项、150.逆波兰表达式求值

有效的括号

        考虑创建一个char栈,当遍历字符串时,若发现左括号,则作入栈操作,当发现右括号时,首先考虑栈是否为空,非空的情况下与栈顶的元素进行比对,若能构成一对有效括号,则弹出该栈顶元素,否则返回false,若最终所有入栈左括号均能匹配有效的右括号(最终栈为空),则字符串中括号有效。算法的时间复杂度为O(n),空间复杂度为O(n)。

class Solution {
public:
    bool isValid(string s) {
        stack<char> left; // 使用一个栈来存储左括号
        int length = s.size();
        if (length % 2 != 0) {
            return false; // 如果字符串长度为奇数,则返回false
        }

        for (int i = 0; i < length; i++) {
            switch (s[i]) {
                case '(':
                case '{':
                case '[':
                    left.push(s[i]); // 将左括号压入栈
                    break;
                case ')':
                    if (left.empty() || left.top() != '(') {
                        return false; // 如果栈为空或者栈顶不是'(',则返回false
                    }
                    left.pop(); // 弹出栈顶元素
                    break;
                case '}':
                    if (left.empty() || left.top() != '{') {
                        return false; // 如果栈为空或者栈顶不是'{',则返回false
                    }
                    left.pop(); // 弹出栈顶元素
                    break;
                case ']':
                    if (left.empty() || left.top() != '[') {
                        return false; // 如果栈为空或者栈顶不是'[',则返回false
                    }
                    left.pop(); // 弹出栈顶元素
                    break;
            }
        }

        return left.empty(); // 如果栈为空,则所有左括号都被匹配
    }
};

删除字符串中的所有相邻重复项

        创建一个char栈,遍历字符串s的所有元素,当栈为空时,将当前字符压入栈temp,否则进行判断,若新遍历到的元素与栈顶元素相同,则栈顶元素出栈,否则当前元素入栈,遍历完成后,由于栈的先入后出原则,将所有元素出栈到一个字符串中,并对字符串进行反转,就能得到删除了所有相邻重复项的字符串。算法的时间复杂度为O(n),空间复杂度为O(n)。

class Solution {
public: // 声明一个公共的类,名为 Solution
    string removeDuplicates(string s) {
        stack<char> temp; // 创建一个名为 temp 的栈,用于存储不重复的字符
        for(int i = 0; i < s.size();i++){ // 遍历字符串 s 的每一个字符
            if(temp.size()==0){ 
                temp.push(s[i]); // 如果栈 temp 为空,将当前字符压入栈 temp
            }
            else{ // 如果栈 temp 不为空
                if(s[i] == temp.top()){
                    temp.pop(); // 如果当前字符与栈顶字符相同,弹出栈顶字符
                }
                else{ 
                    temp.push(s[i]); //如果当前字符与栈顶字符不同将当前字符压入栈temp
                }
            }
        }
        string ans; // 创建一个名为 ans 的新字符串,用于存储结果
        while(temp.size() != 0){ 
            ans += temp.top(); // 当栈 temp 不为空时,将栈顶字符添加到字符串ans
            temp.pop(); // 弹出栈顶字符
        }
        reverse(ans.begin(),ans.end()); // 反转字符串 ans,使其顺序与原始字符串 s 相同
        return ans; // 返回反转后的字符串 ans
    }
}; 

逆波兰表达式求值

逆波兰表达式(也称为后缀表),其数字运算符位于计算数之后,如 1 2 + 表示1+2,考虑到这一点,我们需要遍历整个逆波兰表达式字符串,并需要一个栈来存储遍历中的元素,将遍历到的数字全存入栈中,当遍历到数字运算符时,将栈顶弹出两次,用于计算,计算后的结果重新入栈,若逆波兰表达式是正确的,则当遍历完字符串元素,栈中应该只剩下一个元素,即最后的结果,出栈即可。算法的时间复杂度为O(n),空间复杂度为O(n)。

class Solution {
private:
    std::stack<int> stack_temp;

public:
    int evalRPN(std::vector<std::string>& tokens) {
        int i = 0; // 初始化i
        int num1, num2;
        while (i < tokens.size()) {
            if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {//若token[i]为数字运算符,栈弹出两个元素并进行计算,并将得到结果重新入栈
                num1 = stack_temp.top();
                stack_temp.pop();
                num2 = stack_temp.top();
                stack_temp.pop();
                if (tokens[i] == "+") {
                    stack_temp.push(num2 + num1);
                } else if (tokens[i] == "-") {
                    stack_temp.push(num2 - num1);
                } else if (tokens[i] == "*") {
                    stack_temp.push(num2 * num1);
                } else if (tokens[i] == "/") {
                    if (num1 == 0) {
                        throw std::invalid_argument("Division by zero.");
                    }//这里防止出现分母为0的情况
                    stack_temp.push(num2 / num1);
                }
            } else {
                // 将字符串转换为整数
                stack_temp.push(std::stoi(tokens[i]));
            }
            i++;
        }
        int result = stack_temp.top();//弹出最后保存在栈中的结果,此时若逆波兰表达式正确,则
                                      //只存在一个元素
        stack_temp.pop();
        return result;
    }
};

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值