Leetcode题解-算法-栈和队列

1、用栈实现队列

232. Implement Queue using Stacks(Easy)
Implement the following operations of a queue using stacks.

  • push(x) – Push element x to the back of queue.
  • pop() – Removes the element from in front of queue.
  • peek() – Get the front element.
  • empty() – Return whether the queue is empty.

Example:

MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // returns 1
queue.pop(); // returns 1
queue.empty(); // returns false

问题分析:
用两个栈 a 和 b,每次插入元素都向栈 a 中插入,取出元素时,若栈 b 不为空,取栈顶元素,若栈 b 不为空,将栈 a 中元素依次压入栈 b 中,再取出 b 的栈顶元素。

这里有一个小技巧保存队列首元素,变量 first 保存栈 a 中最早插入的那个元素,即当插入元素时,如果栈 a 为空时,更新 first,如果栈 b 不为空,队列中第一个元素为 b 栈顶元素,若 b 为空,队列中第一个元素为 first。
在这里插入图片描述

在这里插入图片描述

class MyQueue {
private:
    stack<int>a;
    stack<int>b;
    int first;
public:
    /** Initialize your data structure here. */
    MyQueue() {
        
    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        if(a.empty())
            first=x;
        a.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        if(b.empty())
        {
            while(!a.empty())
            {
                b.push(a.top());
                a.pop();
            }
        }
        int tmp=b.top();
        b.pop();
        return tmp;
    }
    
    /** Get the front element. */
    int peek() {
        if(b.empty())
            return first;
        return b.top();
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return a.empty() && b.empty();
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

2、用队列实现栈

225. Implement Stack using Queues(Easy)
Implement the following operations of a stack using queues.

  • push(x) – Push element x onto stack.
  • pop() – Removes the element on top of the stack.
  • top() – Get the top element.
  • empty() – Return whether the stack is empty.

Example:

MyStack stack = new MyStack();
stack.push(1);
stack.push(2);
stack.top(); // returns 2
stack.pop(); // returns 2
stack.empty(); // returns false

方法一:
用一个队列实现,每次插入一个元素,都将原来的队列中的元素依次弹出再插入队列中,保证队列中新插入的元素在队头。

class MyStack {
private:
    queue<int>a;
public:
    /** Initialize your data structure here. */
    MyStack() {
        
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        a.push(x);
        for(int i=0;i<a.size()-1;i++)
        {
            int tmp=a.front();
            a.pop();
            a.push(tmp);
        }
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int tmp=a.front();
        a.pop();
        return tmp;
    }
    
    /** Get the top element. */
    int top() {
        return a.front();
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return a.empty();
    }
};
/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

复杂度分析: push:O(1),pop:O(n)

方法二:
用两个队列 a 和 b 实现栈,插入元素时,统统插入队列 a 中,取出元素时,将 a 中元素依次取出插入队列 b 中,直到只剩下一个元素,取出即可,在将队列 b 中元素放回队列 a 中。

不管向那个队列中插入元素,都要记录最后一个插入的元素是哪一个,该元素为栈顶元素。

复杂度分析: push:O(1),pop:O(n)

class MyStack {
private:
    queue<int>a;
    queue<int>b;
    int fir;
public:
    /** Initialize your data structure here. */
    MyStack() {
        
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        a.push(x);
        fir=x;
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        while(a.size()>1)
        {
            int tmp=a.front();
            a.pop();
            b.push(tmp);
            fir=tmp;
        }
        int top=a.front();
        a.pop();
        queue<int>q=a;
        a=b;
        b=q;
        return top;
    }
    
    /** Get the top element. */
    int top() {
        return fir;
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return a.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

3、最小值栈

155. Min Stack(Easy)
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

  • push(x) – Push element x onto stack.
  • pop() – Removes the element on top of the stack.
  • top() – Get the top element.
  • getMin() – Retrieve the minimum element in the stack.

Example:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> Returns -3.
minStack.pop();
minStack.top(); --> Returns 0.
minStack.getMin(); --> Returns -2.

class MinStack {
private:
    stack<int>a;
    stack<int>min;
public:
    /** initialize your data structure here. */
    MinStack() {
        
    }
    
    void push(int x) {
        a.push(x);
        if(min.empty()||x<=min.top())//相等时也应该压入
            min.push(x);
    }
    
    void pop() {
        if(a.top()==min.top())
            min.pop();
        a.pop();
    }
    
    int top() {
        return a.top();
    }
    
    int getMin() {
        return min.top();
    }
};
/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

4、括号匹配

20. Valid Parentheses(Easy)
Given a string containing just the characters ‘(’, ‘)’, ‘{’, ‘}’, ‘[’ and ‘]’, determine if the input string is valid.

An input string is valid if:

  • Open brackets must be closed by the same type of brackets.
  • Open brackets must be closed in the correct order.

Note that an empty string is also considered valid.

Example 1:

Input: “()”
Output: true

Example 2:

Input: “()[]{}”
Output: true

Example 3:

Input: “(]”
Output: false

Example 4:

Input: “([)]”
Output: false

Example 5:

Input: “{[]}”
Output: true

问题分析:
每碰见 ‘(’, ‘{’, ‘[’ 就将其压入栈中,每碰见 ‘)’, ‘}’, ']'就查看栈如果为空或栈顶元素不匹配返回 false,如果匹配弹出栈顶元素,直到匹配完所有字符,如果栈为空返回 true。

class Solution {
public:
    bool isValid(string s) {
       int n = s.size();
	stack<char>st;
	for (int i = 0; i<n; i++)
	{
		if (s[i] == '(' || s[i] == '[' || s[i] == '{')
			st.push(s[i]);
		else if (s[i] == ')')
		{
            if(st.empty()||st.top() != '(')
                return false;
			st.pop();
		}
		else if (s[i] == ']')
		{
			if(st.empty()||st.top() != '[')
                return false;
			st.pop();
		}
		else if (s[i] == '}')
		{
			if(st.empty()||st.top() != '{')
                return false;
			st.pop();
		}
	}
	if (st.empty())
		return true;
	return false;
    }
};

5、数组中下一个比自己的元素和自己的距离

739. Daily Temperatures(Medium)
Given a list of daily temperatures T, return a list such that, for each day in the input, tells you how many days you would have to wait until a warmer temperature. If there is no future day for which this is possible, put 0 instead.

For example, given the list of temperatures T = [73, 74, 75, 71, 69, 72, 76, 73], your output should be [1, 1, 4, 2, 1, 1, 0, 0].

对于每个元素,找出数组右侧第一个大于自己的那个元素距离自己的距离。

问题分析
从右向左遍历数组,使用栈,栈中元素存放元素的下标,对于一个元素 a,将元素 a,与栈顶元素下标对应的元素作比较,如果大于等于栈顶元素对应的元素,弹出,直到找到找顶下标对应元素大于该元素值的元素,距离就是二者下标之差,每次都需要将新元素下标压入栈中。

要保证栈中的元素从栈顶向栈底是递增的,因为发现一个元素比栈中元素对应的数组元素大时,说明找到更近的距离了,所以栈中弹出栈中无用数据。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& T) {
        vector<int>res(T.size(),0);
        stack<int>s;
        for(int i=T.size()-1;i>=0;i--)
        {
            while(!s.empty() && T[s.top()]<=T[i])
                s.pop();
            if(s.empty())
                res[i]=0;
            else
                res[i]=s.top()-i;
            s.push(i);
        }
        return res;
    }
};

6、循环数组中比当前元素大的下一个元素

503. Next Greater Element II(Medium)
Given a circular array (the next element of the last element is the first element of the array), print the Next Greater Number for every element. The Next Greater Number of a number x is the first greater number to its traversing-order next in the array, which means you could search circularly to find its next greater number. If it doesn’t exist, output -1 for this number.

Example 1:

Input: [1,2,1]
Output: [2,-1,2]
Explanation: The first 1’s next greater number is 2;
The number 2 can’t find next greater number;
The second 1’s next greater number needs to search circularly, which is also 2.

Note: The length of given array won’t exceed 10000.

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int n=nums.size();
        vector<int>res(n,-1);
        for(int i=0;i<n;i++){
            for(int j=1;j<=n;j++){
                if(i+j<n&&nums[i+j]>nums[i]){
                    res[i]=nums[i+j];
                    break;
                }
                else if(i+j>=n&&nums[i+j-n]>nums[i]){
                    res[i]=nums[i+j-n];
                    break;
                }
            }
        }
        return res;
    }
};

方法一:暴力搜索

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int n=nums.size();
        vector<int>res(n,-1);
        for(int i=0;i<n;i++){
            for(int j=1;j<=n;j++){
                if(i+j<n&&nums[i+j]>nums[i]){
                    res[i]=nums[i+j];
                    break;
                }
                else if(i+j>=n&&nums[i+j-n]>nums[i]){
                    res[i]=nums[i+j-n];
                    break;
                }
            }
        }
        return res;
    }
};

时间复杂度:O(n2)
空间复杂度:O(1)

方法二:用栈保存
用栈来保存元素的下标,从尾到头遍历数组,如果当前元素大于栈顶下标对应元素,弹出,直到找到比当前元素大的元素,或着栈为空,表示找不到(-1),从尾到头遍历两次,即得出结论。

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int n=nums.size();
        vector<int>res(n,-1);
        stack<int>s;
        for(int i=2*n-1;i>=0;i--){
            while(!s.empty()&&nums[i%n]>=nums[s.top()])
                s.pop();
            res[i%n]=s.empty()?-1:nums[s.top()];
            s.push(i%n);
        }
        return res;
    }
};

时间复杂度:O(n)
空间复杂度:O(n)

7、字符串解码

394. Decode String(Medium)
给一个字符串 k[encoded_string],表示字符串 encoded_string 出现 k 次。不会存在像 3a 或者 2[4] 这样的输入/

Examples:

s = “3[a]2[bc]”, return “aaabcbc”.
s = “3[a2[c]]”, return “accaccacc”.
s = “2[abc]3[cd]ef”, return “abcabccdcdcdef”.

class Solution {
public:
    string decodeString(string s) {
        if(s.empty()) return s;
        stack<char>st;
        for (int i = 0; i < s.size(); i++){
            if (s[i] == ']'){
                string tmp = "";
                while (st.top() != '['){
                    tmp = st.top() + tmp;
                    st.pop();
                }
                st.pop();
                string num = "";
                while (!st.empty() && isdigit(st.top())){
                    num = st.top() + num;
                    st.pop();
                }
                int n = stoi(num.c_str());
                string newtmp = "";
                for (int i = 0; i < n; i++)
                    newtmp += tmp;
                for (char c : newtmp)
                    st.push(c);
            }
            else
                st.push(s[i]);
        }
        string res = "";
        while (!st.empty()){
            res = st.top() + res;
            st.pop();
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值