【劍指offer】讓抽象問題具體化

ConardLi發表於2019-02-17

1.包含min函式的棧

定義棧的資料結構,請在該型別中實現一個能夠得到棧中所含最小元素的min函式(時間複雜度應為O(1))。

思路

1.定義兩個棧,一個棧用於儲存資料,另一個棧用於儲存每次資料進棧時棧的最小值.

2.每次資料進棧時,將此資料和最小值棧的棧頂元素比較,將二者比較的較小值再次存入最小值棧.

4.資料棧出棧,最小值棧也出棧。

3.這樣最小值棧的棧頂永遠是當前棧的最小值。

程式碼

var dataStack = [];
var minStack = [];
 
function push(node)
{
    dataStack.push(node);
    if(minStack.length === 0 ||  node < min()){
        minStack.push(node);
    }else{
        minStack.push(min());
    }
}
function pop()
{
    minStack.pop();
    return dataStack.pop();
}
function top()
{
    var length = dataStack.length;
    return length>0&&dataStack[length-1]
}
function min()
{
    var length = minStack.length;
    return length>0&&minStack[length-1]
}

2.棧的壓入、彈出序列

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

思路

1.藉助一個輔助棧來儲存資料。

2.將pushV中的資料依次入棧。

3.出棧有可能在任意一次入棧後進行,當出棧資料不再位於棧頂,繼續入棧。

4.所以設定一個索引,記錄當前出棧的位置,每次出棧索引+1。

5.當所有資料入棧完成,如果出棧順序正確,那麼輔助棧應該為空。

程式碼

    function IsPopOrder(pushV, popV) {
      if (!pushV || !popV || pushV.length == 0 || popV.length == 0) {
        return;
      }
      var stack = [];
      var idx = 0;
      for (var i = 0; i < pushV.length; i++) {
        stack.push(pushV[i]);
        while (stack.length && stack[stack.length - 1] == popV[idx]) {
          stack.pop();
          idx++;
        }
      }
      return stack.length == 0;
    }

3.題二叉樹的後續遍歷

輸入一個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則輸出Yes,否則輸出No。假設輸入的陣列的任意兩個數字都互不相同。

思路

1.後序遍歷:分成三部分:最後一個節點為跟節點,第二部分為左子樹的值比跟節點都小,第三部分為右子樹的值比跟節點都大。

2.先檢測左子樹,左側比跟節點小的值都判定為左子樹。

3.除最後一個節點外和左子樹外的其他值為右子樹,右子樹有一個比跟節點小,則返回false。

4.若存在,左、右子樹,遞迴檢測左、右子樹是否複合規範。

程式碼

    function VerifySquenceOfBST(sequence) {
      if (sequence && sequence.length > 0) {
        var root = sequence[sequence.length - 1]
        for (var i = 0; i < sequence.length - 1; i++) {
          if (sequence[i] > root) {
            break;
          }
        }
        for (let j = i; j < sequence.length - 1; j++) {
          if (sequence[j] < root) {
            return false;
          }
        }
        var left = true;
        if (i > 0) {
          left = VerifySquenceOfBST(sequence.slice(0, i));
        }
        var right = true;
        if (i < sequence.length - 1) {
          right = VerifySquenceOfBST(sequence.slice(i, sequence.length - 1));
        }
        return left && right;
      }
    }

4.二叉樹中和為某一值的路徑

輸入一顆二叉樹的跟節點和一個整數,列印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。(注意: 在返回值的list中,陣列長度大的陣列靠前)

思路

1.使用前序遍歷

2.使用一個輔助棧來儲存當前路徑裡的資料

3.記錄一個當前路徑的和

4.遍歷到當前節點後,當前值入路徑棧,和加當前值

5.遞迴左孩子右孩子節點

6.遍歷完一個節點,退回到上一個節點,從路徑棧中移除當前的值,和減當前值

程式碼

    function FindPath(root, expectNumber) {
      var result = [];
      if (!root) {
        return result;
      }
      findPath(root, expectNumber, [], 0, result);
      return result;
    }

    function findPath(node, expectNumber, vector, sum, result) {
      vector.push(node.val);
      sum += node.val;
      var isLeaf = !node.left && !node.right;
      if (isLeaf && sum === expectNumber) {
        result.push(vector.slice(0));
      }
      if (node.left) {
        findPath(node.left, expectNumber, vector, sum, result);
      }
      if (node.right) {
        findPath(node.right, expectNumber, vector, sum, result);
      }
      vector.pop();
    }

相關文章