两个栈实现队列
入队:直接push进stack1
出队:如果stack2中有元素,直接pop;如果stack2中无元素,将stack1中元素依次pop然后push进stack2
我的代码:
void push(int node)
{
tack1.push(node);
}
int pop() {
int tmp;
int ans;
//stack2 is not empty
f(!stack2.empty())
{
ans = stack2.top();
stack2.pop();
return ans;
}
//stack2 is empty
while(!stack1.empty())//ture =1
{
tmp = stack1.top();
stack1.pop();
stack2.push(tmp);
}
ans = stack2.top();
stack2.pop();
return ans;
}
仔细观察后发现,stack2 is not empty时的代码与将stack1元素push进stack2后的代码相同。此外,STL容器中top()函数可以返回值,不需要定义tmp中间变量进行转存,而pop()函数只在容器中删除,无法得到删除的值,故可删去tmp中间变量。对代码进行精简后:
void push(int node)
{
stack1.push(node);
}
int pop()
{
if(stack2.empty())
{
while(!stack1.empty())
{
stack2.push(stack1.top());
stack1.pop();
}
}
int ans = stack2.top();
stack2.pop();
return ans;
}
两个队列实现栈
class MyStack {
public:
queue<int> q1,q2;
MyStack() {
}
void push(int x) {
//将q1中所有元素移至q2
while(!q1.empty())
{
q2.push(q1.front());
q1.pop();
}
q1.push(x);
while(!q2.empty())
{
q1.push(q2.front());
q2.pop();
}
}
int pop() {
int res = q1.front();
q1.pop();
return res;
}
int top() {
return q1.front();
}
bool empty() {
return q1.empty()&&q2.empty();
}
};
key point
将最后进入的元素放置队首,然后将比起先进入“栈”的元素再放到队尾。
包含min函数的栈
所用的全局变量,如果未给出,可在public中自行定义。
get一个空间换时间的例子。
思路: 借助辅助栈min_val,此栈中一直存放着数值最小的元素。当要入栈的元素是最小元素时,同时push进两个栈,当要入栈的元素不是最小元素时,将min_val中的栈顶元素再入栈一次,以保证两个栈的元素个数相同,避免出现min_val栈为空的情况。【我自己想到了用辅助栈,但是只想在辅助栈中存一个元素(即,不断判断元素大小,只在辅助栈中保留一个元素),但是会出现辅助栈空的情况。只能说思路对了一半】
public:
stack<int> normal;
stack<int> min_val;
void push(int value) {
if(min_val.empty() && normal.empty())
{
min_val.push(value);
}
else
{
if(min_val.top() > value) min_val.push(value);
else min_val.push(min_val.top());
}
normal.push(value);
}
void pop() {
normal.pop();
min_val.pop();
}
int top() {
return normal.top();
}
int min() {
return min_val.top();
}
栈的压入、弹出序列对比
思路: 【模拟元素入栈出栈】两个指针i,j分别指向压栈序列和出栈序列,i的内容不等于j的内容,则将i的内容入栈,i++;i的内容等于j的内容,则j++,i++;判断栈顶元素和j内容的关系,然后进行操作;最后栈空则对比正确。
case:
pushV[i] == popV[j],相当于元素pushV[i]入栈之后又出栈,这时又分为两种情况
i == j,此时模拟的是元素入栈之后马上出栈的情况,继续比对下一对元素即可,无需对辅助栈进行操作i > j,此时模拟的是一组元素pushV[0],pushV[1],...,pushV[i-1],pushV[i]入栈之后,pushV[i]出栈的情况。pushV[i]出栈后,又有两种可能:pushV[i+1]入栈,或者pushV[i-1]出栈。若是前者,需要比对的是pushV[i+1]与popV[j+1]的关系。而后者则需要从辅助栈弹出栈顶元素与popV[j]对比。
pushV[i] != popV[j],相当于元素入栈之后没有出栈,所以需要栈暂存pushV[i]
bool IsPopOrder(vector<int> pushV,vector<int> popV)
{
stack<int> st;
for(int i = 0, j = 0; i < pushV.size(); )
{
if(pushV[i] == popV[j])
{
i++;
j++;
while(!st.empty() && st.top() == popV[j]
{
st.pop();
j++;
}
}
else st.push(pushV[i++]);
}
return st.empty();
}
括号匹配
我的思路: 遍历字符串,碰到左括号({[就将其压入栈中,碰到右括号,若此时栈中无左括号,则报错,若栈不为空,则将栈顶元素与该右括号进行匹配,成功则弹栈,否则报错。 关于代码简化:字符串长度为0或者奇数时,前者一定匹配,后者一定不匹配。
bool isValid(string s)
{
int len = s.length();
//奇数
if(len % 2 == 1) return false;
//空字符串
if(len == 0) return true;
//非空偶数长字符串
stack<char> st;
for(int i = 0; i < len; i++)
{
//左括号直接入栈
if(s[i] == '(' || s[i] == '[' || s[i] == '{' ) st.push(s[i]);
else //右括号
{
//stack is not empty
if(!st.empty())
{
if(s[i] == ')' )
{
if(st.top() == '(') st.pop();
else return false;
}
if(s[i] == ']' )
{
if(st.top() == '[') st.pop();
else return false;
}
if(s[i] == '}' )
{
if(st.top() == '{') st.pop();
else return false;
}
}
//栈中无左括号,但是来了一个右括号
else if(st.empty()) return false;
}
}
return st.empty();
}
其他思路:
- 使用函数进行括号匹配
- 使用键值对map
map<char, char> mp = {
{')','('},
{']','['},
{'}','{'}
};
for(char ch : s)
{
if(mp.count(ch))
{
if(st.empty() || st.top() != mp[ch]) return false;
else st.pop();
}
else st.push(ch);
}
return st.empty();
key-point
-
map使用,
map<key,value>,map[key] = value以及map变量的赋值方式。 -
for(char ch:s)等价于for(int i = 0; i < s.length(); i++)
- 换一种入栈方式:入栈右括号 只需比较符号是否相等即可
for(int i = 0; i < len; i++)
{
if(s[i] == '(') st.push(')');
else if(s[i] == '[') st.push(']');
else if(s[i] == '{') st.push('}');
else if(st.empty()|| st.top() != s[i]) return false;
else st.pop();
}
return st.empty();
注意:条件不能换为else if(st.top() != s[i] || st.empty()),会产生越界。原因在于C++中||的使用,A || B 其含义为A或B中任意一个成立则条件成立,但在其实现中,条件A对条件B有“屏蔽作用”,当条件A成立时,不再测试条件B。若将写成上述形式,则可能在栈空时取栈顶元素,所以越界。如,输入}{会在栈空时执行top操作。