257. 二叉樹的所有路徑-利用堆棧跟蹤二叉樹前序遍歷的過程。

做題目前隨便說點

  • 樹是一種抽象數據類型,一種具有樹結構形式的數據集合。

  • 節點個數確定,有層次關係。

  • 有根節點。

  • 除了根,每個節點有且只有一個父節點。

  • 沒有環路。

  • 所有數據結構都可以用鏈表表示或者用數組表示,樹也一樣。

257. 二叉樹的所有路徑

給定一個二叉樹,返回所有從根節點到葉子節點的路徑。

說明: 葉子節點是指沒有子節點的節點。

示例:

輸入:

1
/
2 3

5

輸出: [“1->2->5”, “1->3”]

解釋: 所有根節點到葉子節點的路徑爲: 1->2->5, 1->3

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/binary-tree-paths
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

解題:

審題:

  • 這道理,可以看作是打印葉子節點。順便打印深度遍歷的過程。
  • 自上而下的深度遍歷。
  • 我們採用先序遍歷
  • 那麼從父節點到葉子節點的路徑臨時存放到哪裏呢?
  • 我們可以暴力的創建N個臨時遍歷,把這些屬性放到每個節點的擴展屬性中。但是這樣會加大內存開銷。但是一定可行。
  • 還有一個思路就是寄存到List中,然後再根據一個子節點,和兩個子節點,和無子節點。但是對字符串的操作頻繁,實際上並沒有節省到必要的內。代碼維護成本也高很多。
  • 最終還是建議採用方案一,用節點的擴展屬性。但是內存消耗大。如果採用一個棧存儲性能會好很多。棧的實現可以是數組或者是鏈表。但是在java裏無論是StringBuilder還是Stack都是數組存儲(Stack父類是Vector,同步鎖導致性能不高)

框架代碼如下:

class Solution {
    
     TreeNode rescursive(TreeNode node) {
        if( ... ) {
            return node
        } else {
          // 先序遍歷
           rescursive(node.left);
           rescursive(node.right);
           
        }
     }
    
}

開始解題:



/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public static List<String> list;
    // 相當於備忘錄的棧
    public static Stack<Integer> stack = new Stack();

    // 打印備忘錄
    public static String printStack(int leafNodeVal) {
        StringBuilder builder = new StringBuilder();
        for(int i : stack) {
            builder.append(i + "->");
        }
        builder.append(leafNodeVal);
        return builder.toString();
    }

    void rescursive(TreeNode node) {
        if( node == null ) {
            return ;
        } else {
            // 先序遍歷
            boolean isLeaf = (node.left == null && node.right == null);
            if(isLeaf) {
                // 記錄備忘錄的路徑。由於我們約定不寫葉子節點值到備忘錄,所以不需要退回葉子節點的路徑。
                list.add(printStack(node.val));
            } else {
                // 記一下當前節點
                stack.push(node.val);
                rescursive(node.left);
                rescursive(node.right);
                // 遞歸完子節點後後記將自己節點值撤銷。相當於回退路徑。
                stack.pop();
            }
        }
     }

    public List<String> binaryTreePaths(TreeNode root) {
        list =  new ArrayList();
        rescursive(root);
        return list;
    }
}



總結:

  • 這道題目我們用一個棧來輔助我們,這個棧其實是相當於一個備忘錄,因爲深度遍歷時一個遞推和回溯的過程,免不了在棧裏進進出出的。
  • 所以我們在前序遍歷的時候,就進棧,等後序遍歷的時候就退棧,遇到葉子節點就歸檔到list,其他都是細節問題了。然後確保,不要忘記退棧就好。這道題目最難就是推棧。
  • 其實這道題目有一個優化的點,就是用stringBuilder來代替stack,不需要又是Stack類,又是StringBuilder類。比較這兩個類的底層實現都是數組。StringBuilder也是可以當作Stack來用的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章