【代码随想录Day 3 - 栈和队列 ② 4~5】

本文介绍了如何使用栈和队列数据结构解决编程问题,包括检查有效括号配对(使用栈)和删除字符串中相邻重复项(使用队列)。同时强调了在访问容器元素前进行判空的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Carl 语录

提醒

个人总结

一句话

  1. 访问容器中的元素前,必须判空。 对于任何容器类型,在访问其元素前,必须先检查容器是否为空,以避免出现未定义行为。
    • 否则,若容器为空,访问其元素为非法行为,会引发 未定义行为。如在一个空的vector上使用front()或back()函数,就会引发未定义行为。
  2. for( auto 范围变量名:范围表达式) 进行遍历。
  3. ** for (auto iter = v.begin(); iter != v.end(); ++iter) {std::cout << *iter << ’ ';} ** 进行遍历。

20. 有效的括号

20. 有效的括号

实现目标:

每一个出现的右括号(反括号)都与左括号匹配

思路:

  • 使用 栈:每出现一个右括号,出栈一个左括号,判断是否匹配。

实现过程:

  1. 从头开始遍历,每发现一个左括号,压入栈中;
  2. 每发现一个右括号,栈顶元素出栈,判断是否匹配:若匹配则true

代码:

class Solution {
public:
    bool isValid(string s) {
        stack<char> c;
        for(int i = 0; i < s.length(); i++){
        //检测到左括号,则压入栈
            if(s[i] == '(' || s[i] == '[' || s[i] == '{'){
                c.push(s[i]);
            }

            //检测到右括号
            else{ 
                
            // 若栈为空(即右括号多余)
                if(c.empty()) return false;
            //或栈顶元素不匹配,即则返回false
                if( (s[i] == ')' && c.top() != '(')
                  || (s[i] == ']' && c.top() != '[')
                  || (s[i] == '}' && c.top() != '{') ) return false;
            //若栈不为空,且栈顶元素与其相匹配,则出栈栈顶元素
                c.pop();
            }
        }
        //此时已经遍历完成,若栈中仍有元素(即左括号多余,则返回false
        if(!c.empty()) return false;
        return true;
    }
};

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

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

实现目标:

每次都删除当前相邻且重复的两个元素。删除所有重复组后按原来的顺序输出。

思路:

  • 队列,将元素放入队尾,用下一元素与队尾进行对比,若相同则删去两个元素。再次对比。

实现过程:

  1. 删除多余元素。 队尾元素与新元素对比。记得访问元素前要 对容器判空
  2. deque类型转换为string。 用 空string(“”) 逐个添加队列中的字符。

代码:

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)
class Solution {
public:
    string removeDuplicates(string s) {
        deque<char> queue;
            //注意:front()和back()函数的前提条件是容器中必须至少存在一个元素。
            //如果容器为空,则调用这两个函数会导致未定义行为。
            //故要访问容器的首尾元素时,首先要进行判空,可用empty()或size()
            //是的,对于任何容器类型,在访问其中的元素之前,都需要先检查容器是否为空,以避免出现未定义行为。
            //这不仅适用于 deque(双端队列),也适用于其他序列容器,如 vector、list、forward_list、array 等。
            //甚至对于关联容器,如 set、map、unordered_set、unordered_map 等,在访问其中的元素之前,也需要检查容器是否为空。
   
        queue.push_back(s[0]);
        for(int i = 1; i < s.length(); i++){
       
            //如果队列不为空,且新元素与队尾元素相同,则删去队尾元素
            if(!queue.empty() && queue.back() == s[i]) queue.pop_back();

            //若队列为空,或二者不相同,则将新元素添加至队尾
            else queue.push_back(s[i]);
        }

        //将队列中的元素按从前到后的顺序一个一个地添加到 空string 后
        string result="";
        while(!queue.empty()){
            result += queue.front();

            //front()只是访问元素,pop_front()才是删去队首元素
            queue.pop_front();
        }
        return result;
    }
};

Carl 的优解

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

  • 时间复杂度: O(n)
  • 空间复杂度: O(1), 返回值不计空间复杂度

代码如下:

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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值