更新中。。。
1.有效的括号
2.栈的压入、弹出序列
3.最小栈
4.用栈实现队列
5.下一个更大的数
1.有效的括号
题目描述:给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
*左括号必须用相同类型的右括号闭合
*左括号必须以正确的顺序闭合
*注意空字符串可被认为是有效字符串
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
**解题思路:**设置一个栈,如果加入的是一个左括号,则将其加入,如果加入的是一个右括号,则判断其是否能够与栈顶的括号对应,如果对应,则将栈顶 pop ,否则说明有错。因此经过对字符串的处理,如果最终栈不是空的,说明该字符串不是有效字符串。
class Solution {
public:
bool isValid(string s)
{
stack<char> st;
for(int i=0;i<s.size();i++)
{
if(s[i]=='('||s[i]=='{'||s[i]=='[') //左括号加入
st.push(s[i]);
else if(st.size()>0&&(s[i]==')'&&st.top()=='('||s[i]==']'&&st.top()=='['||s[i]=='}'&&st.top()=='{'))//右括号需要判断能否消除,不能消除即出错
st.pop();
else
return false;
}
if(st.size()==0)
return true;
return false;
}
};
2.栈的压入、弹出序列
题目描述:输入两个整数序列(pushed,poped), pushed表示栈的压入顺序,请判断poped是否为该栈的弹出顺序。 假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
解题思路:这道题是栈系列的一道非常经典的题目,首先我们要借助一个辅助的栈,每次将pushed序列向辅助栈中加入一个元素,每加入一个元素,都要判断是否与当前popped序列当前的输出位置元素相同,如果相同,则将栈目前元素pop处,popped序列位置右移(注意这里是用一个循环,如果top的内容与popped序列位置内容一致则一直pop()。最终如果是合法序列的话最后的栈应该是空的,否则说明非法。
举例:
入栈1,2,3,4,5
出栈4,5,3,2,1
首先1入辅助栈,此时栈顶1≠4,继续入栈2
此时栈顶2≠4,继续入栈3
此时栈顶3≠4,继续入栈4
此时栈顶4=4,出栈4,poped序列向后一位,此时为5,,辅助栈里面是1,2,3
此时栈顶3≠5,继续入栈5
此时栈顶5=5,出栈5,poped序列向后一位,此时为3,,辅助栈里面是1,2,3
….
依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。
class Solution
{
public :
bool IsPopOrder ( vector < int > pushed , vector < int > poped )
{
//如果两个序列为空则返回false
if (pushed . empty () || poped . empty ())
return false ;
stack < int > s ;
//用于标识弹出序列的位置
int j = 0 ;
for ( int i = 0 ; i < pushed . size (); i ++) //扫描入栈序列
{
s . push ( pushed[ i ]); //push元素直到栈顶元素为pop序列中的元素
while (! s . empty () && s.top() == pushed[j ]) //相等时,辅助栈出栈,弹出序列索引加一
{
s . pop ();
j ++;
}
}
return s . empty (); //如果为空,则说明入栈序列和出栈序列相匹配,为true,否则为false
}
};
3.最小栈
题目描述:设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
**解题思路:**用两个栈,一个存放数据,一个存放最小值。
举例:
入栈 3
| | | |
| | | |
|_4_| |_4_|
s1 s2
入栈6 ,6大于s2的栈顶,故不压入
| | | |
| 6 | | |
|_4_| |_4_|
s1 s2
入栈 2 ,2小于最小值栈的栈顶,故将其入栈
| 2 | | |
| 6 | | 2 |
|_4_| |_4_|
s1 s2
出栈 2,发现2是最小栈的栈顶,故s2也出栈
| | | |
| 6 | | |
|_4_| |_4_|
s1 s2
出栈 6,发现6不是最小栈的栈顶,因此s2 不处理
| | | |
| | | |
|_4_| |_4_|
s1 s2
class MinStack
{
private :
stack < int > s1 ; //存数据
stack < int > s2 ; //存各阶段最小数
public :
void push ( int x )
{
s1 . push ( x );
if ( s2 . empty () || x <= s2.top ())
s2 . push ( x ); //如果s2为空,或者存入数小于等于之前最小数,则传入s2
}
void pop ()
{
if ( s1 . top () == s2 . top ())
s2 . pop (); //如果pop的是当前极小值,则s2也跟着pop
s1 . pop ();
}
int top ()
{
return s1 . top ();//返回data的栈顶即可
}
int getMin ()
{
return s2 . top (); //栈顶元素为当前最小数
}
};
4.用栈实现队列
解题思路:用两个栈,插入 s1借助辅助栈s2将元素插入到栈底
举例:假如将序列[2,3]用栈存储来实现队列
入栈 2 ,此时s1,s2栈为空,将2入s1
| | | |
| | | |
|_2_| |_ _|
s1 s2
入栈3 ,此时s1不为空,出s1栈顶元素入s2中,再将3入栈s1,此时s2不为空,将s2栈顶元素入s1.输出序列[2,3]
| | | |
| | | |
|_ _| |_2_|
s1 s2
| | | |
| | | |
|_3_| |_2_|
s1 s2
| | | |
| 2 | | |
|_3_| |_ _|
s1 s2
class MyQueue
{
private :
stack < int > s1 ; //主栈
stack < int > s2 ; //辅助栈
public :
/** 插入元素 */
void push ( int x )
{
while (! s1 . empty ()) //s1转移到s2
{
s2 . push ( s1 . top ());
s1 . pop ();
}
s1 . push ( x ); //在s1中插入元素(处在栈底位置)
while (! s2 . empty ()) //s2转移回s1
{
s1 . push ( s2 . top ());
s2 . pop ();
}
}
/** 删除并返回队列元素 */
int pop ()
{
int top_element = s1 . top ();
s1 . pop ();
return top_element ;
}
/**获取栈顶元素 */
int top ()
{
return s1 . top ();
}
/** 返回栈是否为空*/
bool empty ()
{
return s1 . empty ();
}
};
单调栈:
单调栈是比较特殊的栈结构,分为单调递增栈和单调递减栈,即从栈底元素到栈顶元素呈单调递增或单调递减,栈内序列满足单调性的栈;
单调栈用来解决下一个更大(更小)的元素相关问题.
5.下一个更大的元素
题目描述:给定两个 没有重复元素 的数组 s1,s2.其中s1 是 s2 的子集。找到 s1中每个元素在 s2中的下一个比其大的值。
s1 中数字 x 的下一个更大元素是指 x 在s2中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 − 1。
解题思路:建立递减栈,对 s2中元素遍历,将元素依次放入递减栈,如果放入过程中,需要pop,则说明该元素是需要被pop出元素的下一个更大的数字,此时建立一个映射map,将该关系存入map中,遍历结束后,如果栈中还有元素,则将其pop出,且其对应的map值为-1,表示其后面没有比它更大的元素
对s1中的元素依次取map中对应的匹配即可.
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2)
{
stack<int> min_stack;
map<int,int> HASH;
for(int i=0;i<nums2.size();i++)
{
while(!min_stack.empty()&&min_stack.top()<nums2[i]) //将小于num2[i]的元素pop出且建立映射
{
HASH[min_stack.top()]=nums2[i];
min_stack.pop();
}
min_stack.push(nums2[i]);
}
while(!min_stack.empty()) //对于栈中剩余元素建立映射
{
HASH[min_stack.top()]=-1;
min_stack.pop();
}
vector<int> result;
for(int i=0;i<nums1.size();i++) //遍历取映射即可
result.push_back(HASH[nums1[i]]);
return result;
}
};