DAY9.用栈实现队列、用队列实现栈、括号匹配、删除相邻重复项

用栈实现队列(leetcode第232题)

题目

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

思路

需要了解一些c++中栈操作的语法:

在C++中,栈操作通常使用标准库中的std::stack容器适配器。std::stack基于其他容器(如std::dequestd::liststd::vector)实现,默认使用std::deque作为底层容器。

以下是std::stack的基本操作语法:

1. 包含头文件
#include 
2. 声明栈
std::stack<int> myStack;  // 声明一个存储int类型元素的栈
3. 压栈操作 (push)
myStack.push(10);  // 将元素10压入栈顶
myStack.push(20);  // 将元素20压入栈顶
4. 访问栈顶元素 (top)
int topElement = myStack.top();  // 获取栈顶元素,但不移除它
5. 弹栈操作 (pop)
myStack.pop();  // 移除栈顶元素
6. 检查栈是否为空 (empty)
if (myStack.empty()) {
    std::cout << "栈为空" << std::endl;
} else {
    std::cout << "栈不为空" << std::endl;
}
7. 获取栈的大小 (size)
std::size_t stackSize = myStack.size();  // 获取栈中元素的数量
8. 示例代码
#include 
#include 

int main() {
    std::stack<int> myStack;

    // 压栈
    myStack.push(10);
    myStack.push(20);
    myStack.push(30);

    // 访问栈顶元素
    std::cout << "栈顶元素: " << myStack.top() << std::endl;

    // 弹栈
    myStack.pop();
    std::cout << "弹栈后的栈顶元素: " << myStack.top() << std::endl;

    // 检查栈是否为空
    if (myStack.empty()) {
        std::cout << "栈为空" << std::endl;
    } else {
        std::cout << "栈不为空" << std::endl;
    }

    // 获取栈的大小
    std::cout << "栈的大小: " << myStack.size() << std::endl;

    return 0;
}
9. 输出结果
栈顶元素: 30
弹栈后的栈顶元素: 20
栈不为空
栈的大小: 2
10. 注意事项
  • std::stack不支持直接遍历元素,因为它是基于LIFO(后进先出)原则设计的。
  • 如果你需要遍历栈中的元素,可以考虑使用其他容器(如std::vectorstd::deque)来模拟栈的行为。

通过这些操作,你可以在C++中轻松地使用栈数据结构。

class MyQueue {
public:
    stack<int> Mystack1;
    stack<int> Mystack2;
    MyQueue() {
        
    }
    
    void push(int x) {
         int tmp;
        while(!Mystack2.empty()){
            tmp=Mystack2.top();
            Mystack2.pop();
            Mystack1.push(tmp);
        }
        Mystack1.push(x);
    }
    
    int pop() {
        int tmp;
        while(!Mystack1.empty()){
            tmp=Mystack1.top();
            Mystack1.pop();
            Mystack2.push(tmp);
        }
        tmp=Mystack2.top();
        Mystack2.pop();
        return tmp;
    }
    
    int peek() {
        int tmp;
        while(!Mystack1.empty()){
            tmp=Mystack1.top();
            Mystack1.pop();
            Mystack2.push(tmp);
        }
        tmp=Mystack2.top();
        return tmp;
    }
    
    bool empty() {
        return Mystack1.empty()&&Mystack2.empty();
    }
};

感觉效率很低

对比反思

class MyQueue {
public:
    stack<int> stIn;
    stack<int> stOut;
    /** Initialize your data structure here. */
    MyQueue() {

    }
    /** Push element x to the back of queue. */
    void push(int x) {
        stIn.push(x);
    }

    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        // 只有当stOut为空的时候,再从stIn里导入数据(导入stIn全部数据)
        if (stOut.empty()) {
            // 从stIn导入数据直到stIn为空
            while(!stIn.empty()) {
                stOut.push(stIn.top());
                stIn.pop();
            }
        }
        int result = stOut.top();
        stOut.pop();
        return result;
    }

    /** Get the front element. */
    int peek() {
        int res = this->pop(); // 直接使用已有的pop函数
        stOut.push(res); // 因为pop函数弹出了元素res,所以再添加回去
        return res;
    }

    /** Returns whether the queue is empty. */
    bool empty() {
        return stIn.empty() && stOut.empty();
    }
};

这种做法更加巧妙,关键点在于只有当Mystack2用完时,再从Mystack1里面导入,节约了数据倒来倒去的时间。

  • 时间复杂度: 都为O(1)。pop和peek看起来像O(n),实际上一个循环n会被使用n次,最后还是O(1)。
  • 空间复杂度: O(n)

用队列实现栈(leetcode第225题)

题目

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppopempty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsizeis empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
  • 一个队列也可以实现

解题思路

class MyStack {
public:
    queue<int> Myque;
    int size;
    MyStack() {
        size=0;
    }
    
    void push(int x) {
        Myque.push(x);
        size++;
    }
    
    int pop() {
        int tmp;
        for(int i=0;i<size-1;i++){
            tmp=Myque.front();
            Myque.pop();
            Myque.push(tmp);
        }
         tmp=Myque.front();
           Myque.pop();
        size--;
        return tmp;
    }
    
    int top() {
        int tmp;
        for(int i=0;i<size;i++){
            tmp=Myque.front();
            Myque.pop();
            Myque.push(tmp);
        }
        return tmp;
    }
    
    bool empty() {
        return size==0;
    }
};

复杂度有点高

对比反思

和代码随想录思路一样的

有效的括号(leetcode第20题)

题目

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

有效字符串需满足:

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

示例 1:

**输入:**s = “()”

**输出:**true

示例 2:

**输入:**s = “()[]{}”

**输出:**true

示例 3:

**输入:**s = “(]”

**输出:**false

示例 4:

**输入:**s = “([])”

**输出:**true

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

思路

我想用三个栈分别匹配三种括号,最后如果栈都为空则匹配成功

鉴于三种符合不能交叉,所以一个栈就行

class Solution {
public:
    bool isValid(string s) {
        stack<int> MyStack;
        
        
        for(int i=0;i<s.size();i++){
            switch (s[i])
            {
            case '(':
                /* code */
                MyStack.push(0);
                break;
            case ')':
                /* code */
                if(MyStack.empty()||MyStack.top()!=0)return 0;
                else MyStack.pop();
                break;
            case '[':
                /* code */
                MyStack.push(1);
                break;
            case ']':
                /* code */
                if(MyStack.empty()||MyStack.top()!=1)return 0;
                else MyStack.pop();
                break;
            case '{':
                /* code */
                MyStack.push(2);
                break;
            case '}':
                /* code */
                if(MyStack.empty()||MyStack.top()!=2)return 0;
                else MyStack.pop();
                break;
            
            default:
                return 0;
                break;
            }
        }
        if(MyStack.empty())return 1;
        return 0;
    }
};

删除字符串中的所有相邻重复项(leetcode第1047题)

题目

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

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

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

示例:

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

提示:

  • 1 <= S.length <= 20000
  • S 仅由小写英文字母组成。

思路

类似于括号匹配

class Solution {
public:
    string removeDuplicates(string s) {
        stack<int> MyStack;
        for(int i=0;i<s.size();i++){
            if(!MyStack.empty()){
                if(MyStack.top()==s[i]){
                    MyStack.pop();
                    
                }else{
                    MyStack.push(s[i]);
                }
            }else{
                MyStack.push(s[i]);
            }
        }
        string res;
        
        int index=MyStack.size();
        res.resize(MyStack.size());
        while(!MyStack.empty()){
            res[--index]=MyStack.top();
            MyStack.pop();
        }
        return res;
    }
};

对比反思

可以直接拿字符串当栈

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++,数据结构,算法)