Day22(栈)

💫说得简单,要做到真的很难,不知道为什么自己丧失了获取新知识的动力,能力。


📆学习日期:2025年3月27日21:13:56

💻学习内容:有效的括号 | 删除字符串中的相邻重复项

⏲️学习时长:1h50min

练习题目1-有效的括号
题目描述

20. 有效的括号 - 力扣(LeetCode) 简单

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

有效字符串需满足:

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

示例 1:

输入:s = "()"

输出:true

示例 2:

输入:s = "()[]{}"

输出:true

示例 3:

输入:s = "(]"

输出:false

示例 4:

输入:s = "([])"

输出:true

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成
解题思路
  • 整体思路&&注意事项
  1. 使用 解决问题的经典题目
  2. 3种不匹配的情况:
  • 多出半个/多个左括号
  • 左右括号数量正确,但样式不匹配
  • 多出半个/多个右括号

  • 代码实现

模拟3种不匹配的情况

  1. 情况1
  • 遍历字符串,遇到左括号,则将对应的右括号入栈
  • 遇到右括号,与栈顶元素相比较,若匹配,则弹出相应的括号
  • 遍历结束后,若栈不为空,则"多了左括号",返回false
  1. 情况2
  • 遍历字符串,遇到左括号,则将对应的右括号入栈
  • 遇到右括号,与栈顶元素相比较,若不匹配,则发现不匹配,返回false
  1. 情况3
  • 遍历字符串,遇到左括号,则将对应的右括号入栈
  • 遇到右括号,与栈顶元素相比较,若匹配,则弹出相应的括号
  • 遇到右括号,但发现栈为空,说明字符串多出“右括号”,返回false

剪枝条件:

若字符串长度为奇数,则一定不匹配。

Bug

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(']');
        }
        else if(st.empty()||st.top()!=s[i]){//不匹配情况2/3
            return false;

        }
        else{
            st.pop();//匹配,弹出
        }

        }
        
        // if(st.empty()) return true;//匹配
        // else return false;//情况1:多余左括号 
        return st.empty();
    }
};

时间复杂度:O(n),其中 n 是字符串 s 的长度。

空间复杂度:O(n),其中 n 是字符串 s 的长度。

练习题目2-删除字符串中的相邻重复项
题目描述

1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode) 简单

给出由小写字母组成的字符串 s重复项删除操作会选择两个相邻且相同的字母,并删除它们。

s 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

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

提示:

  1. 1 <= s.length <= 105
  2. s 仅由小写英文字母组成。
解题思路
  • 整体思路&&注意事项
  1. 使用 栈 解决问题的经典题目
  2. 与括号匹配有点类似,匹配后弹出即可。

  • 代码实现
  1. 遍历字符串,入栈
  2. 判断元素是否与栈顶元素相同,弹出。
  3. 反向输出栈元素得到最终结果

Bug

class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> st;

        for(int i=0;i<s.size();i++){
            if(st.empty()||s[i]!=st.top()) st.push(s[i]);//栈为空,或者不匹配,则入栈,不要操作空栈
            else st.pop();//匹配,弹出
        }

        // //存放结果
        // string result;
        // int j=0;
        // while(!st.empty()){
        //     result[j]=st.top(); //这种是错误的
        //     st.pop();
        //     j++;
        //     //str.puch_back('A');
        // }

        //存放结果
        string result;
        while(!st.empty()){
            result.push_back(st.top());
            st.pop();
        }

        reverse(result.begin(),result.end());//反转

        return result;
        
        
    }
};
class Solution {
public:
    string removeDuplicates(string S) {
        stack<char> st;
        for (char s : S) {
            if (st.empty() || s != st.top()) {
                st.push(s);
            } else {
                st.pop(); // s 与 st.top()相等的情况
            }
        }
        string result = "";
        while (!st.empty()) { // 将栈中元素放到result字符串汇总
            result += st.top();
            st.pop();
        }
        reverse (result.begin(), result.end()); // 此时字符串需要反转一下
        return result;

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

当然可以拿字符串直接作为栈,这样省去了栈还要转为字符串的操作。

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;
    }
};
//在下面的 C++ 代码中,由于 std::string 类本身就提供了类似「入栈」和「出栈」的接口
//因此我们直接将需要被返回的字符串作为栈即可。
//对于其他的语言,如果字符串类没有提供相应的接口,则需要在遍历完成字符串后,
//使用栈中的字符显式地构造出需要被返回的字符串。
class Solution {
public:
    string removeDuplicates(string s) {
        string stk;
        for (char ch : s) {
            if (!stk.empty() && stk.back() == ch) {
                stk.pop_back();
            } else {
                stk.push_back(ch);
            }
        }
        return stk;
    }
};

时间复杂度:O(n),其中 n 是字符串的长度。我们只需要遍历该字符串一次。

空间复杂度:O(n) 或 O(1),取决于使用的语言提供的字符串类是否提供了类似「入栈」和「出栈」的接口。注意返回值不计入空间复杂度。

作者:力扣官方题解

链接:1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)

来源:力扣(LeetCode)

学习总结
  1. C++中字符串的反转操作
  1. string可以直接作为栈(string的相关知识) 待了解
相关题目

括号生成

中等

最长有效括号

困难

删除无效的括号

困难

检查替换后的词是否有效

中等

判断一个括号字符串是否有效

中等

移动片段得到字符串

中等


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

中等

从字符串中移除星号

中等

最小化字符串长度

简单

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值