劍指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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章