劍指Offer面試題:20.棧的壓入、彈出序列


一、題目:棧的壓入、彈出序列

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

二、解題思路

2.1 核心步驟

正確的彈出序列

不正確的彈出序列

  通過分析以上序列,可以得出:

  • 如果下一個彈出的數字剛好是棧頂數字,那么直接彈出
  • 如果下一個彈出的數字不在棧頂,我們把壓棧序列中還沒有入棧的數字壓入輔助棧,直到把下一個需要彈出的數字壓入棧頂為止。
  • 如果所有的數字都壓入棧了仍然沒有找到下一個彈出的數字,那么該序列不可能是一個彈出序列。

2.2 代碼實現

    public static bool IsPopOrder(int[] pushOrder, int[] popOrder, int length)
    {
        bool possible = false;

        if (pushOrder != null && popOrder != null && length > 0)
        {
            int nextPush = 0; // 指向下一個要push的元素的index
            int nextPop = 0;  // 指向下一個要pop的元素的index
            int pop = 0;      // 指向popOrder的首個元素的index
            int push = 0;     // 指向pushOrder的首個元素的index

            Stack<int> stackData = new Stack<int>();
            while (nextPop - pop < length)
            {
                // 當輔助棧的棧頂元素不是要彈出的元素
                // 先壓入一些數字入棧
                while (stackData.Count == 0 || stackData.Peek() != popOrder[nextPop])
                {
                    // 如果所有數字都壓入輔助棧了,退出循環
                    if (nextPush - push == length)
                    {
                        break;
                    }

                    stackData.Push(pushOrder[nextPush]);
                    nextPush++;
                }

                // 說明沒有匹配成功
                if (stackData.Peek() != popOrder[nextPop])
                {
                    break;
                }

                stackData.Pop();
                nextPop++;
            }

            if (stackData.Count == 0 && nextPop - pop == length)
            {
                possible = true;
            }
        }

        return possible;
    }

三、單元測試

3.1 功能測試

    [TestMethod]
    public void OrderTest1()
    {
        int length = 5;
        int[] push = { 1, 2, 3, 4, 5 };
        int[] pop = { 4, 5, 3, 2, 1 };

        Assert.AreEqual(StackHelper.IsPopOrder(push, pop, length), true);
    }

    [TestMethod]
    public void OrderTest2()
    {
        int length = 5;
        int[] push = { 1, 2, 3, 4, 5 };
        int[] pop = { 3, 5, 4, 2, 1 };

        Assert.AreEqual(StackHelper.IsPopOrder(push, pop, length), true);
    }

    [TestMethod]
    public void OrderTest3()
    {
        int length = 5;
        int[] push = { 1, 2, 3, 4, 5 };
        int[] pop = { 4, 3, 5, 1, 2 };

        Assert.AreEqual(StackHelper.IsPopOrder(push, pop, length), false);
    }

    [TestMethod]
    public void OrderTest4()
    {
        int length = 5;
        int[] push = { 1, 2, 3, 4, 5 };
        int[] pop = { 3, 5, 4, 1, 2 };

        Assert.AreEqual(StackHelper.IsPopOrder(push, pop, length), false);
    }

3.2 特殊輸入測試

    // push和pop序列只有一個數字且不同
    [TestMethod]
    public void OrderTest5()
    {
        int length = 1;
        int[] push = { 1 };
        int[] pop = { 2 };

        Assert.AreEqual(StackHelper.IsPopOrder(push, pop, length), false);
    }

    // push和pop序列只有一個數字且相同
    [TestMethod]
    public void OrderTest6()
    {
        int length = 1;
        int[] push = { 1 };
        int[] pop = { 1 };

        Assert.AreEqual(StackHelper.IsPopOrder(push, pop, length), true);
    }

    // NULL指針
    [TestMethod]
    public void OrderTest7()
    {
        Assert.AreEqual(StackHelper.IsPopOrder(null, null, 0), false);
    }

3.3 測試結果

  (1)測試通過情況

  (2)代碼覆蓋率

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM