目录
-
实现栈的求最小值函数(剑指欧肥儿)
class Solution {
public:
void push(int value) {
StackInt.push(value);
if(StackMin.empty())
StackMin.push(value);
else if(StackMin.top()<value)
StackMin.push(StackMin.top());
else
StackMin.push(value);
}
void pop() {
if(!StackInt.empty())
{
StackInt.pop();
StackMin.pop();
}
}
int top() {
return StackInt.top();
}
int min() {
return StackMin.top();
}
private:
stack<int> StackInt;
stack<int> StackMin;
};
代码思路:
- 声明两个栈,一个是放所有值的栈(StackIn),一个是顶部放最小值的栈(StackMin)
- 压入时,两个栈都要压入数,StackIN压入value;而StackMin需要和它栈中top位置的值比较,如果value小于等于StackMin.top()压入value,如果value大于StackMin.top()则压入StackMin.top()
- 弹出时,两个栈都弹出顶端的数,这样保证了两个栈的同步性,保证StackMin的顶部是当前StackIn整个栈的最小值。
- 返回StackIn的顶端的值。
- 返回StackIn里的最小值,即StackMin里的顶端值。
-
栈的压入,弹出序列(剑指欧肥儿)
题目描述:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
解题答案:
class Solution{
public:
bool IsPopOrder(vector<int> pushV, vector<int> popV){
if(pushV.size() != popV.size() || popV.size() == 0 || pushV.size() == 0){
return false;
}
stack <int> st //加入一个辅助栈
int id = 0;
for(int i = 0; i < popV.size(); i++){
while(st.empty() || st.top() != popV[i]){
if(id >= st.top )
{//以防越界
return false;
}
st.push(pushV[id++]);
}
st.pop();
}
if(st.empty()){
return true;
}else{
return false;
}
}
}
代码思路:
- 边界值判断,去除不符合条件的输入向量
- 依次遍历输出栈(popV)的每一个数,再循环判断popV对应的数是否等于st(辅助栈)顶端的数,如果不等于则继续压入pushV的数,如果等于则st弹出这个数。注意循环的时候有可能一直没找到符合条件的数,就会变成死循环,故判断是否变量下标越界,越界直接false(因为这意味着弹出序列包含了压入序列里没有的数)。
- 最后判断辅助栈st是否为空,为空则弹出序列正确,否则不正确。
向量vector的大小:vector.size()
取向量vector里的数:vector[i] //取数类似于数组
这道题的思维:
借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。
举例:
入栈1,2,3,4,5
出栈4,5,3,2,1
首先1入辅助栈,此时栈顶1≠4,继续入栈2
此时栈顶2≠4,继续入栈3
此时栈顶3≠4,继续入栈4
此时栈顶4=4,出栈4,弹出序列向后一位,此时为5,,辅助栈里面是1,2,3
此时栈顶3≠5,继续入栈5
此时栈顶5=5,出栈5,弹出序列向后一位,此时为3,,辅助栈里面是1,2,3
-
用两个栈实现队列(剑指欧肥儿)
题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
代码:
class Solution{
public:
void push(int node){
stack1.push(node);
}
int pop(){
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.top());
stack1.pop();
}
}
int a = stack2.top();
stack2.pop();
return a;
}
private:
stack<int> stack1;
stack<int> stack2;
}
代码思路:
- 压栈就压stack1.
- 弹出时,首先检测stack2是不是空的,如果是空的,就把stack1里从顶到底压入stack1,再弹出stack2顶部数据;如果stack2不是空的,则直接把stack2的顶部数据弹出。
- 这样做的好处,不会每一次压栈都要重新生成一次stack2(因为生成stack2时间为把stack1全部n个节点压入,时间为n),只有在stack2全部用完了,才会重新生成stack2。节约时间,而且省空间。
代码核心:
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.top());
stack1.pop();
}
}
-
滑动窗口的最大值(剑指欧肥儿)
题目描述:
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}
解题代码:
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
vector<int> max;
if(num.size() < size || size < 1) return max;
int m;
for(int i = 0; i < num.size() - size + 1; i++){ //根据max中有多少个元素来遍历
m = num[i];
for(int j = i + 1; j < i + size; j++){
if( m < num [j]){
m = num[j];
}
}
max.push_back(m);
}
return max;
}
};
这道题的思维:
- 不要引入栈!这道题和栈没关系!
- 切入点很重要,切入点正确了,这道题就很简单了。