剑指Offer-栈

剑指Offer-栈

此处两道题为《剑指Offer》中举例让抽象问题具体化的21和22题,记录一下实现思路。

题1,包含min函数的栈:定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数

思路:除了正常存入数据的普通栈外,定义一个辅助栈,辅助栈中每次压入当前最小值。例如压入3、4、2、1,首先普通栈压入3,当前最小值为3,压入辅助栈;普通栈压入4,当前最小值还为3,压入辅助栈;普通栈压入2,当前最小值为2,压入辅助栈;最后普通栈压入1,当前最小值为1,压入辅助栈;
则普通栈为1、2、4、3,辅助栈为1、2、3、3,辅助栈每次弹出的都是当前最小值。

代码:

class Solution {
public:
  stack<int> normal;
  stack<int> order;
  int min_value = INT_MAX;
  void push(int value) {
    normal.push(value);
    if(value<min_value)
      min_value = value;
    order.push(min_value);
  }
  void pop() {
    normal.pop();
    order.pop();
  }
  int top() {
    return normal.top();
  }
  int min() {
    return order.top();
  }
};

题2,栈的压入、弹出序列:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路1:举个例子,我们压入7、6、4、5、3、8、9,其中一个弹出的序列可以为4、3、9、8、5、6、7,我们可以发现,弹出序列中,压入序列的最后一个数字9之前的数字相对压入序列是正序,9之后的数字相对压入序列是逆序。于是我们考虑首先在弹出序列中寻找压入序列最后一个数所在的位置,然后判断这个数前边的序列是否是正序,这个数后边的序列是否是逆序,符合这个条件则输出true,否则输出false

思路2:构造辅助栈,当栈为空或者当前栈顶元素不为弹出序列中当前元素的话,则从输入序列中继续压栈,当输入序列全部压入但是还是栈顶元素依旧不为当前弹出序列中当前元素的话,则不符合要求。
举个例子:压栈序列为1、2、3、4、5,弹出序列为4、5、3、2、1
1. 弹出序列第一个数为4,当前栈为空,则压入1、2、3、4,弹出4
2. 弹出序列第二个数为5,当前栈为1、2、3,3!=5,则压入5(此时已全部入栈),弹出5
3. 弹出序列第三个数为3,当前栈为1、2、3,3=3,则弹出3
4. 弹出序列第四个数为2,当前栈为1、2,2=2,弹出2
5. 弹出序列第五个数为1,当前栈为1,1=1,弹出1
6. 弹出序列已遍历完,返回true

如果更改一下,弹出序列为4、5、3、1、2,则:
1. 弹出序列第一个数为4,当前栈为空,则压入1、2、3、4,弹出4
2. 弹出序列第二个数为5,当前栈为1、2、3,3!=5,则压入5(此时已全部入栈),弹出5
3. 弹出序列第三个数为3,当前栈为1、2、3,3=3,则弹出3
4. 弹出序列第四个数为1,当前栈为1、2,2!=1,且已全部入栈,返回false

此题代码如下:

bool IsPopOrder(vector<int> pushV,vector<int> popV) {
  if(pushV.size()==0 || popV.size()==0) return false;
  int split_value = *(pushV.end()-1);
  auto split_pos = find(popV.begin(),popV.end(),split_value);
  auto it1 = pushV.begin();
  auto it2 = popV.begin();
  while(it2!=split_pos && it1!=pushV.end()-1) {
    if(*it2 == *it1)
      ++it2;
    ++it1;
  }
  if(it2!=split_pos) return false;
  it1 = pushV.begin();
  it2 = popV.end()-1;
  while(it2!=split_pos && it1!=pushV.end()-1) {
    if(*it2 == *it1)
      --it2;
    ++it1;
  }
  if(it2!=split_pos) return false;
  return true;
}

bool IsPopOrder1(vector<int> pushV,vector<int> popV) {
  if(pushV.size()==0 || popV.size()==0) return false;
  auto it1 = pushV.begin();
  auto it2 = popV.begin();
  stack<int> s;
  while(it2!=popV.end()) {
    while(s.empty() || s.top()!=*it2) {
      if(it1==pushV.end()) return false;
      s.push(*it1);
      ++it1;
    }
    s.pop();
    ++it2;
  }
  return true;
}
发布了47 篇原创文章 · 获赞 32 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章