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;
}
};