咱們今天繼續來看看週五留下的習題:java
面試題:輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷二個序列是否爲該棧的彈出順序。假設壓入棧的全部數字均不相等。例如:壓入序列爲{1,2,3,4,5},那{4,5,3,2,1} 就是該棧的彈出順序,而{4,3,5,1,2} 明顯就不符合要求;面試
這道題仍是比較容易想到思路,很直觀的想法就是創建一個輔助棧,把輸入的第一個序列中的數字依次壓入該輔助棧,並按照第二個序列的順序依次從該棧中彈出數字。數組
同樣是老方法,咱們先準備測試用例:學習
判斷一個序列是否是棧的彈出序列的規律:若是下一個彈出的數字恰好是棧頂數字,那麼直接彈出。若是下一個彈出的數字不在棧頂,咱們把壓棧序列中尚未入棧的數字壓入輔助棧,直到把下一個須要彈出的數字壓入棧頂爲止。若是全部的數字都壓入棧了仍然沒有找到下一個彈出的數字,那麼該序列不多是一個彈出序列。測試
然而有的小夥伴仍是容易被繞暈,這時候不妨咱們能夠直接做一個表格來模擬他們的壓棧出棧過程,數據就採用咱們題設中的數據吧~spa
用做圖和模擬數據更容易給面試官一個你是個喜歡思考的好同事喲~code
首先看看咱們正確的數據。it
判斷操做 | 操做 | 棧 | 彈出數字 |
---|---|---|---|
棧沒數據,push 數組還有數據、壓入 | 壓入 | 1 | |
棧頂是 1,不等於pop[0],push 數組還有數據、壓入 | 壓入 | 一、2 | |
棧頂是 2,不等於pop[0],push 數組還有數據、壓入 | 壓入 | 一、二、3 | |
棧頂是 3,不等於pop[0],push 數組還有數據、壓入 | 壓入 | 一、二、三、4 | |
棧頂是 4,等於pop[0],彈出數字 4 | 彈出 | 一、二、3 | 4 |
棧頂是 3,不等於pop[1],push 數組還有數據、壓入 | 壓入 | 一、二、三、5 | |
棧頂是 5,等於pop[1],彈出數字 5 | 彈出 | 一、二、3 | 5 |
棧頂是 3,等於pop[2],彈出數字 3 | 彈出 | 一、2 | 3 |
棧頂是 2,等於pop[3],彈出數字 2 | 彈出 | 1 | 2 |
棧頂是 1,等於pop[4],彈出數字 1 | 彈出 | 1 |
實際上咱們在草稿紙上並不須要作這麼標準的表格,只要能表現意思便可。io
咱們仔細觀察能夠得知,咱們判斷壓入仍是彈出甚至是得出肯定結論的標準是,先看當前棧頂元素和彈出的數字是否相等,若是相等則直接彈出;若是不相等則直接看看壓入數組中還有沒有元素,若是有則直接壓入到輔助棧;若是已經沒有數據則表明第二個序列不是第一個序列的彈出棧。table
實際上咱們心中已經大概知道怎麼寫了。
private static boolean isPushStack(int[] push, int[] pop) { if (push == null || pop == null || pop.length != push.length) return false; Stack<Integer> stack = new Stack<>(); int j = 0; for (int i = 0; i < pop.length; i++) { // 第一步判斷棧頂元素是否和 pop[i] 相等 if (!stack.isEmpty() && pop[i] == stack.peek()) { // 若是相等則直接 pop() stack.pop(); } else { // 棧頂和 pop[i] 不相等,則判斷 push 數組還有沒有數據 // 若是 push 數組沒數據了,棧頂元素又不等於 pop[i],則說明不符合要求 if (j == push.length) return false; while (j < push.length) { // 若是還有數據,則直接 push stack.push(push[j]); ++j; // push 後繼續判斷棧頂元素是否和 pop[i] 相等; if (pop[i] == stack.peek()) { // 若是相等則彈出棧,而且推出內層循環 stack.pop(); break; } } } } return true; }
寫畢代碼後,咱們得用本身事先準備的測試用例測試一下。
測試 1 和測試 2 咱們已經考慮到了,這樣的狀況直接在功能以前就判斷,不符合條件的直接返回 false,測試經過。
傳入{1,2,3,4,5} 和 {4,5,3,2,1}:
傳入 {1,2,3,4,5} 和 {4,3,5,1,2}:
傳入 {1} 和 {2}:
進入循環,i = 0,pop[i] = 2,進入 else 語句,不相等,直接進入 while 循環,push 後棧內元素爲 {1},棧頂元素和 pop[i] 不相等,此時 j = 1,不符合 while 循環條件。循環結束,外循環也結束,返回 true。測試不經過。
因此咱們如今應該着重處理一下單個數字的狀況,分析後明顯能夠獲得,咱們要判斷這種狀況只須要再判斷結束 for 循環後棧內是否還有元素和 push 裏面仍是否有元素便可。
因此在最後增長一個條件判斷便可。
public class Test16 { private static boolean isPushStack(int[] push, int[] pop) { if (push == null || pop == null || pop.length != push.length) return false; Stack<Integer> stack = new Stack<>(); int j = 0; for (int i = 0; i < pop.length; i++) { // 第一步判斷棧頂元素是否和 pop[i] 相等 if (!stack.isEmpty() && pop[i] == stack.peek()) { // 若是相等則直接 pop() stack.pop(); } else { // 棧頂和 pop[i] 不相等,則判斷 push 數組還有沒有數據 // 若是 push 數組沒數據了,棧頂元素又不等於 pop[i],則說明不符合要求 if (j == push.length) return false; while (j < push.length) { // 若是還有數據,則直接 push stack.push(push[j]); ++j; // push 後繼續判斷棧頂元素是否和 pop[i] 相等; if (pop[i] == stack.peek()) { // 若是相等則彈出棧,而且推出內層循環 stack.pop(); break; } } } } // 增長判斷 if (!stack.isEmpty() && j == push.length) return false; return true; } public static void main(String[] args) { int[] push = {1, 2, 3, 4, 5}; int[] pop1 = {4, 5, 3, 2, 1}; int[] pop2 = {3, 5, 4, 2, 1}; int[] pop3 = {4, 3, 5, 1, 2}; int[] pop4 = {3, 5, 4, 1, 2}; System.out.println(isPushStack(push, pop1)); System.out.println(isPushStack(push, pop2)); System.out.println(isPushStack(push, pop3)); System.out.println(isPushStack(push, pop4)); int[] push1 = {1}; int[] pop5 = {2}; System.out.println(isPushStack(push1, pop5)); int[] push2 = {1}; int[] pop6 = {1}; System.out.println(isPushStack(push2, pop6)); } }
上面在代碼邏輯上並無作多少操做,因此咱們只須要再傳入 {1} 和 {1} 測試就能夠了。
直接進入到 while 循環,push 後棧內元素爲 {1},由於棧頂元素剛剛等於 pop[0],因此推出數字 1。此後棧內無元素,因此直接返回 true。
我親愛的小夥伴想必也必定在上面的分析中收穫到東西了吧,這也是南塵給你們的箴言。
本次學習的方法將很是有效,不信你們能夠試試下明天的拓展題。
面試題:從上到下打印二叉樹的每一個結點,同一層按照從左到右的順序打印。例如數的結構以下:
1
2 3
4 5 6 7則依次打印 一、二、三、四、五、六、7