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

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