leetcode学习记录_栈

剑指 Offer 09. 用两个栈实现队列

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

来源:力扣(LeetCode)
思路:定义两个栈st1 , st2 插入元素只靠st1,删除元素只靠st2
在这里插入图片描述

class CQueue {
    stack<int> st1 , st2;
public:
    CQueue() {//清空两个栈
    	while(!st1.empty())
    	{
    		st1.pop();
    	}
    	while(!st2.empty())
    	{
    		st2.pop();
    	}
    }
    
    void appendTail(int value) {
    	st1.emplace(value);
    }
    
    int deleteHead() {  
    	if(st1.empty() && st2.empty())
    	{
    		return -1;
    	}
    	if(st2.empty())
    	{
    		while(!st1.empty())
    		{
    			st2.emplace(st1.top());
    			st1.pop();
    		}
    	}
    	int buf = st2.top();
    	st2.pop();
    	return buf;
    }
};


20. 有效的括号

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

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
来源:力扣(LeetCode)
看见这题的第一眼,我脑子里就闪过了栈,因为后缀表达式的它的运算都是依靠栈来实现的,
就因为栈的特性:先进后出

思路路路路路:
用哈希表存放6个括号及其对应的值(自定义,能配对就行了)
然后从左开始遍历字符串,遇见左括号就入栈,遇见右括号就看栈顶的括号是不是能与当前右括号配对,如果能配对,对应的左括号出栈,如果不能配对,就说明这字符串里的括号是无效的
在这里插入图片描述
特殊情况:没有左括号的情况
如果只有右括号,即栈里一直为空,但是我们还需要比较栈顶元素是否能配对呢,这时读取stack::top的话程序就会崩溃

class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        bool res = true;
        unordered_map<char , int> map = 
        {
            {'(' , 1 },{')' , -1 },
            {'[' , 2 },{']' , -2 },
            {'{' , 3 },{'}' , -3 },
        };
        for(char ch : s)
        {
            int buf = map[ch];
            if(buf > 0) st.push(ch);
//配对,以及处理特殊情况            
            else if(!st.empty() && buf + map[st.top()] == 0)  st.pop();
            else res = false;
        }
//因为配对成功我们就出栈,所以如果最后栈里还有元素的话,
//就说明还有没配对成功的括号,就代表这个括号字符串无效        
        if(!st.empty()) res = false;
        return res;
    }
};


394. 字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

来源:力扣(LeetCode)

这题一开始自己用栈写了一会,被嵌套的括号搞傻了,没啥思路,就看了一下官方题解,没想到是要在栈上完成解码的过程,最后在填入到字符串内,我一开始就想着一边解码一边填入结果字符串,就没写出来。
思路:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后说明一下:我在代码中用的是第二个栈来中转并得到临时字符串,但其实可以通过insert在临时字符串头部插入字符来直接构建整个临时字符串,没必要用第二个栈,我只是懒得改代码了而已
代码:

class Solution {
public:
    string decodeString(string s) {
        stack<char> st;
        stack<char> buf;
        for(char& ch : s)
        {
            if(ch != ']') st.push(ch);//如果字符是数字、字母和左括号就入栈
            else//如果是右括号就开始解码
            {
                while(st.top() != '[')
                {//把字符填入第二个栈
                    buf.push(st.top());
                    st.pop();
                } 
                st.pop();//去掉栈内左括号
                string temp;
                while(!buf.empty())
                {//利用第二个栈构建字符串
                    temp += buf.top();
                    buf.pop();
                }

                
                int num = 0;
                int carry = 0;
                while(!st.empty() && st.top() >= '0' && st.top() <= '9')
                {//获取数字,因为数字可能是多位的
                    num += (st.top()-'0')*pow(10,carry++);
                    st.pop();
                }


                while(num>=1)
                {//根据数字重复填入栈
                    for(char& ch : temp)
                    {
                        st.push(ch);
                    }
                    --num;
                }
            }
        }
        int size = st.size();
        string res(size,'0');
        for(--size;size>=0;--size)
        {//根据栈 构建结果字符串
            res[size] = st.top();
            st.pop();
        }
        return res;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timathy33

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值