刷题记录(栈)

0 栈和队列

0.1 栈(stack)

先进后出,后进先出
栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。
在这里插入图片描述

0.2 队列(queue)

先进先出

0.3 优先队列(priority_queue)

小堆序实现从大到小排序,大堆序实现从小到大排序
小堆序堆顶的元素一定是堆里最小的,大堆序堆顶的元素一定是堆里最大的

1用两个栈实现队列

栈(stack):先进后出
队列(cqueue):先进先出
思路:
sin用于,sout用于
加入元素:直接添加进sin
删除元素:

  • 情况1:sout不为空,则直接返回sout.top(),并pop()
  • 情况2:sout为空,若sin不为空,则将sin中的全部元素给sout,若sin为空,则说明此时没有元素,返回-1
class CQueue {
    stack<int> sin;
    stack<int> sout;
public:
    CQueue() {

    }
    
    void appendTail(int value) {
        sin.emplace(value);
    }
    
    int deleteHead() {
        if (!sout.empty()) {
            int n = sout.top();
            sout.pop();
            return n;
        }
        else {
            if (sin.empty()) return -1;
            else {
                while (!sin.empty()) {
                    sout.emplace(sin.top());
                    sin.pop();
                }
                int n = sout.top();
                sout.pop();
                return n;
                
            }
        }
    }
};

2 用队列实现栈

2.1 两个队列

用一个队列q1作为主栈,实现所有功能,另一个队q2列作为插入数据时的缓冲队列
加入元素时:

  • 先将q1中的所有元素放到q2中,接着在q1中加入元素,此时刚加入的元素就位于队列前端,也就实现了后加先出,再将q2中的元素再导入q1
    删除,返回top等功能就只需要在q1进行
class MyStack {
    queue<int> q1;
    queue<int> q2;
public:
    MyStack() {

    }
    
    void push(int x) {
        while (!q1.empty()) {
            q2.emplace(q1.front());
            q1.pop();
        }
        q1.emplace(x);
        while (!q2.empty()) {
            q1.emplace(q2.front());
            q2.pop();
        }
    }
    
    int pop() {
        int n = q1.front();
        q1.pop();
        return n;
    }
    
    int top() {
        return q1.front();
    }
    
    bool empty() {
        return q1.empty();
    }
};

2.2 一个队列实现栈

一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。

class MyStack {
public:
    queue<int> que;
    /** Initialize your data structure here. */
    MyStack() {

    }
    /** Push element x onto stack. */
    void push(int x) {
        que.push(x);
    }
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int size = que.size();
        size--;
        while (size--) { // 将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部
            que.push(que.front());
            que.pop();
        }
        int result = que.front(); // 此时弹出的元素顺序就是栈的顺序了
        que.pop();
        return result;
    }

    /** Get the top element. */
    int top() {
        return que.back();
    }

    /** Returns whether the stack is empty. */
    bool empty() {
        return que.empty();
    }
};

2有效的括号

思路一(栈):

  • 若字符串个数不为偶数个(%2==1),则必是有问题的
  • 构造一个栈,遍历字符串,若是( [ {则入栈
  • 若是 ) ] },则看此时栈是否为空,为空肯定是false,不为空还需看栈顶是否为对应的括号,并将栈顶移出。
  • 最后若栈不为空,说明里面还有多余的( [ {,说明也有问题。
    思路二(栈+哈希)

哈希表unordered_map用法:{{key,value}}

  • 定义:unordered_map<int,int>unordered_map<string, double>
  • 插入:例如(“ABC” -> 5.45) 插入,hash[“ABC”]=5.45
  • 查询:hash[“ABC”]会返回5.45
  • 判断key是否存在:hash.count(“ABC”) != 0 或 hash.find(“ABC”) != hash.end()
    eg: unordered_map<char,int> m{{'(',1},{'[',2},{'{',3},{')',4},{']',5},{'}',6}};
  • 关联性:std::unorederd_map 是一个关联容器,其中的元素根据键来引用,而不是根据索引来引用。
  • 无序性:在内部,std::unordered_map中的元素不会根据其键值或映射值按任何特定顺序排序,而是根据其哈希值组织到桶中,以允许通过键值直接快速访问各个元素(常量的平均时间复杂度)。
  • 唯一性:std::unorederd_map中的元素的键是唯一的
    for(char c:s):遍历字符串。相当于C++的:
for( int i = 0; i < s.length(); i++)
{ 
	s[i]....	
}
for (char c : s)//复制一个s字符串再进行遍历操作
for (char& c : s)//直接引用原字符串进行遍历操作
for(auto &c:s)
for(auto c:s)

auto是c++程序设计语言的关键字。用于两种情况:

  • (1)声明变量时根据初始化表达式自动推断该变量的类型

  • (2)声明函数时函数返回值的占位符

  • 举例:对于值x=1;既可以声明: int x=1 或 long x=1,也可以直接声明 auto x=1

3包含min函数的栈

要求:能够得到栈的最小元素的 min 函数在该栈中
思路:构造一个栈A满足正常的push和pop,再构造一个有序栈B将最小值放到栈顶。

  • 最小栈在初始化时应该添加一个极大值INT_MAX
    注:/因为在添加第一个值的时候,最小栈里面没有元素,所以用一个极大值保证首个元素能够添加进最小栈。
  • 栈A正常添加元素,若添加的元素<=有序栈B的栈顶元素,才将该元素添加进栈B。
    -栈A正常删除栈顶元素。若删除的元素==有序栈B的栈顶元素,栈B才删除该元素(保证若最小值出栈时栈A和栈B一起删除它)
class MinStack {
public:
    /** initialize your data structure here. */
    stack<int>st,stmin;
    MinStack() {
        stmin.push(INT_MAX);//因为在下方,添加第一个值的时候,stmin.top()没有值,又因为只有一个值,肯定是最小的,所以用一个极大值保证第一个值能够添加进最小栈st_min
    }
    
    void push(int x) {
        st.push(x);
        if( x <= stmin.top() )
        {
            stmin.push(x);
        }
    }
    
    void pop() {
        if(st.top()==stmin.top())stmin.pop();//若最上面的是最小值,则需把另一个辅助栈也删掉
        st.pop();

    }
    
    int top() {
        return st.top();
    }
    
    int min() {
        return stmin.top();
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值