判斷一個序列是否可能爲出棧序列、打印全部可能的出棧序列

題目1:判斷一個序列是否可能爲出棧序列

輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否可能爲該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的一個彈出序列,但4,3,5,1,2就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)

劍指offer 22題:https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106

解答

雙指針:i 指向pushV的元素,j 指向popV的元素。

新建一個棧,將數組pushV逐個入棧,

當棧頂元素等於popV [ j ] 時 (while循環,不是if),就將其出棧,同時 j 後移

當遍歷完pushV時,判斷棧是否爲空,若爲空則返回true。

時間複雜度O(n)

bool IsPopOrder(vector<int> pushV,vector<int> popV) {
    int n = pushV.size();
    if(n != popV.size()) return false;   // 包含了有一個數組爲空的情況 
    // 後面代碼能夠應對2個數組都爲空的情況,故不單獨考慮
    
    stack<int> st;
    int j = 0;
    for(int i=0; i<n; i++){
        st.push(pushV[i]);
        while(j<n && st.top() == popV[j]){
            st.pop();
            j++;
        }
    }
    return st.empty();
}

 

題目2

給定一個長度爲n的入棧序列(不重複),打印全部可能的出棧序列

解答

全部可能的出棧序列數爲卡特蘭數:

C_n = \binom{2n}{n}-\binom{2n}{n-1} =\frac{1}{n+1}\binom{2n}{n}

方法1:枚舉所有排列結果,然後調用題目1的函數判斷。時間複雜度O(n! * n)

方法2:只枚舉可能的出棧序列,時間複雜度O(Cn).

當我們模擬時會發現,除開始時必須將第一個元素入棧外,其他時候面臨着出棧或入棧新元素兩種情況。可用遞歸實現。

int cnt = 0;
void FindPopSeqs(deque<int> in,vector<int> out,stack<int> Stack)
{
    if(in.size() == 0) {    // 遞歸邊界
        while(!Stack.empty()){
            out.push_back(Stack.top());
            Stack.pop();
        }
        for(int i=0; i<out.size(); i++)
            cout<<out[i]<<" ";
        cout<<endl;
        cnt++;
        return;
    }

    // 有2個選擇:入棧或出棧(順序可互換)
    // 1.入棧
    Stack.push(in.front());
    in.pop_front();
    FindPopSeqs(in, out, Stack);
    // 恢復(關鍵點)
    in.push_front(Stack.top());
    Stack.pop();

    // 2.出棧
    if(Stack.size() > 0) {
        out.push_back(Stack.top());
        Stack.pop();
        FindPopSeqs(in, out, Stack);
        // 恢復(可忽略這步,因爲參數都是值傳遞且後面已無遞歸)
        //Stack.push(out.back());
        //out.pop_back();
    }
}

int main(){
    vector<int> in{1,2,3}, out;
    stack<int> Stack;

    deque<int> _in(in.begin(), in.end());   // 也可用list,要在兩端插入/刪除
    FindPopSeqs(_in, out, Stack);
    cout<<cnt<<endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章