栈与队列

1. 由两个栈组成的最小队列

class MyQueue {
public:
    /** Initialize your data structure here. */
    stack<int> stack_push, stack_pop;
    MyQueue() {}

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

    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        if (stack_pop.empty()) {
            while (!stack_push.empty()) {
                 stack_pop.push(stack_push.top());
                 stack_push.pop();
            }
        }
        int value = stack_pop.top();
        stack_pop.pop();
        return value;
    }

    /** Get the front element. */
    int peek() {
        if (stack_pop.empty()) {
            while (!stack_push.empty()) {
                stack_pop.push(stack_push.top());
                stack_push.pop();
            }
        }
        return stack_pop.top();
    }

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

2. 设计一个带有getMin功能的栈

class MinStack {
public:
    /** initialize your data structure here. */
    stack<pair<int, int> > s;
    int minnum;
    MinStack() {
        minnum = 999999;
    }

    void push(int x) {
        if (s.empty()) {
            minnum = x;
        } else {
            minnum = x < s.top().second ? x : s.top().second;
        }
        // x为元素,minnum为此时栈的最小元素
        s.push(make_pair(x, minnum));
    }

    void pop() {
        s.pop();
    }

    int top() {
        return s.top().first;
    }

    int getMin() {
        return s.top().second;
    }
};

3. 仅用递归和栈操作实现逆序一个栈

// 取出栈底元素并将其从栈中移除
int getAndRemoveLastElement(stack<int>& stack) {
    int result = stack.top();
    stack.pop();
    if (stack.empty()) {
        return result;
    } else {
        int last = getAndRemoveLastElement(stack);
        stack.push(result);
        return last;
    }
}

// 递归,取出栈底元素,旋转栈的内容,再将刚才取出的栈底元素推进栈,实现栈的逆序
void reverse(stack<int>& stack) {
    if (stack.empty()) return;
    int i = getAndRemoveLastElement(stack);
    reverse(stack);
    stack.push(i);
}

4. 用一个辅助栈实现另一个栈的排序

/* 主要思路有二:
1. 如果cur小于或等于help的栈顶元素,则将cur直接压入help
2. 如果cur大于help的栈顶元素,则将help的元素逐一弹出,逐一压入stack,
直到cur小于或等于help的栈顶元素,再将cur压入help。
*/
stack<int> help;

void sortStackByStack(stack<int>& stack) {
    while (!stack.empty()) {
        int cur = stack.top();
        stack.pop();
        while (!help.empty() && cur > help.top()) {
            stack.push(help.top());
            help.pop();
        }
        help.push(cur);
    }
    while (!help.empty()) {
        stack.push(help.top());
        help.pop();
    }
}

5. 用栈来求解汉诺塔问题

修改经典的汉诺塔规则:从左到右、从右到左必须要先经过中间。

递归版

int process(int num, string left, string mid, string right, 
    string from, string to) {
    if (num == 1) { // 递归的终止条件
        if (from == mid || to == mid) {
            cout << "Move 1 from " << from << " to " << to << endl;
            return 1;           
        } else {
            cout << "Move 1 from " << from << " to " << mid << endl;
            cout << "Move 1 from " << mid  << " to " << to << endl;
            return 2;
        }
    }
    // 从中间到两边 或者 从两边到中间
    if (from == mid || to == mid) {
        string another = (from == left || to == left) ? right : left;
        int part1 = process(num-1, left, mid, right, from, another);
        int part2 = 1;
        cout << "Move " << num << " from " << from << " to " << to << endl;
        int part3 = process(num-1, left, mid, right, another, to);
        return part1 + part2 + part3;
    } else { // 从左边到右边 或者 从右边到左边
        int part1 = process(num-1, left, mid, right, from, to);
        int part2 = 1;
        cout << "Move " << num << " from " << from << " to " << mid << endl;
        int part3 = process(num-1, left, mid, right, to, from);
        int part4 = 1;
        cout << "Move " << num << " from " << mid << " to " << to << endl;
        int part5 = process(num-1, left, mid, right, from, to);
        return part1 + part2 + part3 + part4 + part5;
    }
}

int hanoiProblem(int num, string left, string mid, string right) {
    if (num < 1) return 0;
    // 初始问题:将num个塔从左边移动到右边
    return process(num, left, mid, right, left, right);
}

非递归版本

enum Action {
    No, LToM, MToR, RToM, MToL
};

stack<int> lS, mS, rS;

int fStackTotStack(vector<Action>& record, Action preNoAct, Action nowAct,
        stack<int>& fStack, stack<int>& tStack, string from, string to) {
    // 满足不违背相邻不可逆原则、小压大原则
    if (record[0] != preNoAct && fStack.top() < tStack.top()) {
        tStack.push(fStack.top());
        fStack.pop();
        cout << "Move " << tStack.top() << " from " << from << " to " << to << endl; 
        record[0] = nowAct; // 记得当前操作,避免下一次与这次相反
        return 1;   // 移动一次操作
    }
}

int hanoiProblem1(int num, string left, string mid, string right) {
    lS.push(INT_MAX);
    mS.push(INT_MAX);
    rS.push(INT_MAX);
    // 初始化数据
    for (int i = num; i > 0; --i) {
        lS.push(i);
    }
    vector<Action> record;
    record.push_back(No);
    int step = 0;
    while (rS.size() != num+1) { // 包括INT_MAX在内是num+1个
        step += fStackTotStack(record, LToM, MToL, mS, lS, mid, left);
        step += fStackTotStack(record, MToL, LToM, lS, mS, left, mid);
        step += fStackTotStack(record, MToR, RToM, rS, mS, right, mid);
        step += fStackTotStack(record, RToM, MToR, mS, rS, mid, right);
    }
    return step;
}

6. 生成窗口最大数组

// 输入: 整形数组arr, 窗口大小为w
// 输出: 一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值
int* getMaxWindow(int* arr, int size, int w) {
    if (size == 0 || w < 1 || size < w)
        return NULL;
    list<int> list;
    int count = 0;
    int* res = new int[size-w+1];
    for (int i = 0; i < size; i++) {
        // 保证队列里的下标对应的值是降序
        while (!list.empty() && arr[list.back()] <= arr[i]) {
            list.pop_back();
        }
        list.push_back(i);
        if (list.front() == i-w) { // 下标过期
            list.pop_front();
        }
        if (i >= w-1) {  // 记录每个窗口的最大值
            res[count++] = arr[list.front()];
        }
    }
    return res;
}

7. 下一个较大元素

给定一个int数组A及数组的大小n,返回一个int数组,代表比每个元素大的下一个元素, 若不存在则为-1。保证数组中元素均为正整数。

class NextElement {
public:
    vector<int> findNext(vector<int> A, int n) {
        // write code here
        vector<int> res;
        stack<int> stack;
        stack.push(-1);
        // 从后往前遍历
        for (int i = n-1; i >= 0; i--) {
            int top = stack.top();
            // 每次取出栈顶元素,如果栈顶元素不为-1,且当前元素>栈顶元素,pop栈顶元素,直至栈顶元素>当前元素,才将当前元素入栈       
            while (top != -1 && stack.top() < A[i]) {
                stack.pop();
                top = stack.top();
            }
            // 如果当前元素<栈顶元素,则当前元素直接入栈
            stack.push(A[i]);
            res.insert(res.begin(), top);
        }
        return res;
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值