打卡Day11

今日继续学栈与队列。

20.有效的括号

栈的经典题目,但比我上次做的那个复杂点,上次做的那个字符串只包含 ' ( ' 和 ' ) ' ,解法也很简单,遇到左括号就压入栈,遇到右括号就出栈,最后看字符串遍历完栈是否为空/栈为空时字符串是否遍历完就行了。但今天这个题复杂一点,字符串不仅有三种括号,而且要求左右括号必须一一配对。

题目内容:给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

我的代码

class Solution {
public:
    bool isValid(string s) {
        
        if(s.size() % 2 != 0) return false;
        stack<char> st;
        for(auto i : s) {
            if(i == '(') {
                st.push(')');
            }else if(i == '{') {
                st.push('}');
            }else if(i == '[') {
                st.push(']');
            }
            if(i == ')' || i == '}' || i == ']') {
                if(st.empty()) {
                    return false;
                }
                char temp = st.top();
                st.pop();
                if(temp != i) {
                    return false;
                }
                
            } 
        }
        if(!st.empty()) return false;
        return true;
    }
};

思路

括号不匹配无非三种情况:

1.左括号多了

2.右括号多了

3.左右括号不匹配

遇到一个左括号就把对应的右括号压入栈(如果直接把左括号压入栈的话,遍历到右括号的时候还要对类型配对进行判断,万一左右括号跳着来的就更复杂了),遇到右括号就弹出栈顶元素,相等则继续遍历,不相等直接return false,这处理了情况3;左括号多了那么对应的栈的元素也多了,这会导致遍历完了字符串栈还不为空,所以在循环结束时判一下空就好了,这处理了情况1;右括号多了即右括号还没遍历完栈就已经空了,所以在遍历到右括号的时候先判下栈是否为空。

视频里还提到了“剪枝”,即代码开头就判断字符串长度是否为奇数,是奇数的话一定不匹配,直接return false,我感觉这放某些赛制里可以骗分哎)并且尝试提交了一下竟然能通过59/74个用例...

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

题目内容:给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

我的代码
class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> st;
        for(auto i : s) {
            if(!st.empty()) {
                char temp = st.top();
                if(temp == i) {
                    st.pop();
                    continue;
                }
            }
            st.push(i);
        }
        string result = "";
        while(!st.empty()) {
            result += st.top();
            st.pop();
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

思路:初始时栈为空,压入字符串第一个元素,往后继续遍历,栈不为空的时候将当前遍历元素与栈顶元素比较,一样的话将栈顶元素弹出,然后continue直接进入下一次循环;不一样的话就把该元素压入栈。栈里操作的是s元素的复制品,最后还要把栈里的元素转换为一个字符串再返回。思路就是一个个取出来放进字符串里,由于栈先入后出,所以还要翻转一下字符串再返回(自己写的时候根本没转换!)。代码随想录还提供了一种直接定义一个新字符串result,将result当栈使用(因为string可以操作back,push_back()和pop_back() )。

150.逆波兰表达式求值

题目内容:给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

示例 1:

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

我的代码

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long> st;
        for(int i = 0; i < tokens.size(); i++) {
            if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
                
                long long temp1 = st.top();
                st.pop();
                long long temp2 = st.top();
                st.pop();
                long long temp3 = 0;
                if(tokens[i] == "+") {
                    temp3 = temp1 + temp2;
                }else if(tokens[i] == "-") {
                    temp3 = temp2 - temp1;
                }else if(tokens[i] == "*") {
                    temp3 = temp2 * temp1;
                }else if(tokens[i] == "/") {
                    temp3 = temp2 / temp1;
                }
                st.push(temp3);
            }else{
                st.push(stoll(tokens[i]));
            }
        }
        int res = st.top();
        return res;
    }
};

反思:这道题其实就是一个后缀表达式问题,思路是对的,遇到数字就入栈,遇到运算符就把两个数字弹出,计算结果,再让结果入栈,遍历完字符串数组的时候返回栈顶值就行。写的时候有以下几个误区:

1.栈里存放的是数字和计算的结果,应当为long long类型(力扣后台开的数字比较大)

2.tokens是一个字符串数组,因此判断该字符串是不是数组实际上并不容易,因为数字长度不定,判断运算符倒是很容易,判断完运算符剩余的字符串直接类型转换再压入栈就好了(类型转换也是新学的 stoi转换为int型,stoll转换为long long型)

3.判断字符时第一次写了tokens[i] == '+' ;tokens的元素都是字符串类型的,比较的时候要用双引号。

一天补两天卡,累死老娘了。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值