有關樹的算法題小結

有關樹的算法題小結

:happy: 一點點小總結,後續繼續補充

富察·容音 當題中提到有關樹的結構時,可以從以下幾個方向考慮:遞歸(居多)、棧、隊列。比如以下幾題:

遞歸

對於二叉樹,其結構較爲固定,很容易想到把一棵樹的問題分解爲左右子樹的問題,這樣可以嘗試使用下遞歸的思路。在遞歸的同時,記錄下變量的值(例如節點、深度),可以解決某些問題(例如:題目1 題目2)。這裏可以注意遞歸的方式,是左中右、右中左題目3。對於搜索二叉樹中兩種遍歷方式可以解決不同問題,例如使用右中左的方式則可以獲取較大值,例如 題目

題目0: 求二叉樹中序遍歷結果

public class BinaryTreeInorderTraversal {
    /**
     * 二叉樹中序排序,遞歸
     * @param root 根節點
     * @param list 記錄
     */
    private void solution(TreeNode root, List<Integer> list) {
        if (root.left != null) {
            solution(root.left, list);
        }
        if (root != null) {
            list.add(root.val);
        }
        if (root.right != null) {
            solution(root.right, list);
        }
    }
​
​
    /**
     * 二叉樹中序排序,非遞歸
     *
     * @param root 根節點
     *             思路:
     *             *1:遍歷左子樹入棧*
     *             *2:pop出一個,取出值*
     *             *3:對右子樹繼續操作*
     *             *4:重複3-4*
     */
    private List<Integer> solution(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
​
        pushAllLeft(root, stack);
​
        while (!stack.empty()) {
            TreeNode node = stack.pop();
            list.add(node.val);
            pushAllLeft(node.right, stack);
        }
        return list;
    }
    private void pushAllLeft(TreeNode root, Stack<TreeNode> stack) {
        while (null != root) {
            stack.push(root);
            root = root.left;
        }
    }
}

 

題目1: 求取根到葉子節點的路徑

/**
 * https://leetcode.com/problems/binary-tree-paths/description/
 */
public class BinaryTreePaths {
    List<String> resultList = new ArrayList<String>();
​
    /**
     * 遞歸 找到跟到葉子節點路徑輸出。這裏直接記錄遞歸過程中節點的值。
     * @param root
     * @return 路徑輸出
     */
    public List<String> solution(TreeNode root) {
        if (root == null) {
            return resultList;
        }
        findPaths(root, root.val + "");
        return resultList;
    }
    private void findPaths(TreeNode node, String path) {
        if (node.left == null && node.right == null) {
            resultList.add(path);
        }
        if (node.left != null) {
            findPaths(node.left, path + "->" + node.left.val);
        }
        if (node.right != null) {
            findPaths(node.right, path + "->" + node.right.val);
        }
    }
}
​

題目2:巧用遞歸1:倒序按行輸出節點的值

/**
 * 倒序按行輸出節點的值
 * 例如:
 * Given binary tree [3,9,20,null,null,15,7],
 * 3
 * / \
 * 9  20
 * /  \
 * 15   7
 * return its bottom-up level order traversal as:
 * [
 * [15,7],
 * [9,20],
 * [3]
 * ]
 * <p/>
 * https://leetcode.com/problems/binary-tree-level-order-traversal-ii/description
 */
public class BinaryTreeLevelOrderTraversal {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> list = new LinkedList<List<Integer>>();
​
        levleMaker(list, root, 0);
        return list;
    }
​
    /**
     * 倒序 按行輸出節點值,這裏採用了遞歸的方式,在遞歸的過程中使用深度控制節點的位置
     * @param list  返回值
     * @param root  根節點
     * @param level 深度
     *              思路:在遍歷的時候,根據深度new、並插入list
     */
    private void levleMaker(List<List<Integer>> list, TreeNode root, int level) {
        if (root == null) return;
        if (list.size() <= level) {
            list.add(new LinkedList<Integer>());
        }
        levleMaker(list, root.left, level + 1);
        levleMaker(list, root.right, level + 1);
        list.get(list.size() - 1 - level).add(root.val);
    }
}

題目3:巧用遞歸2 :搜索二叉樹,每個節點加上比他大的節點

  Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST  is changed to the original key plus sum of all keys greater than the original key in BST.
  Example:
  Input: The root of a Binary Search Tree like this:
  5
  /   \
  2     13
  Output: The root of a Greater Tree like this:
  18
  /   \
  20     13
 https://leetcode.com/problems/convert-bst-to-greater-tree/description/
​
public class ConvertBSTtoGreaterTree {
    int sum = 0;
​
    /**
     * 搜索二叉樹,每個節點加上比他大的節點
     *
     * @param root 根節點
     * @return 根節點
     * 思路:
     * 1:遞歸從大到小遍歷,右中(記錄和)左
     * (我們可以做一個正序遍歷來遍歷樹的節點。在這個過程中,我們跟蹤到目前爲止我們已經遍歷的所有節點的運行總和。)
     */
    public TreeNode convertBST(TreeNode root) {
        if (root == null)
            return null;
        convertBST(root.right);
​
        root.val += sum;
        sum = root.val;
​
        convertBST(root.left);
        return root;
    }
}

隊列

題目4:倒序按行輸出節點的值。同題目2,但此時使用隊列的方式

  /**
     * 廣度優先遍歷算法
     * @param root
     * @return
     */
    public List<List<Integer>> levelOrderBottom2(TreeNode root) {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        if (root == null) return list;
​
        Queue<TreeNode> queue = new ArrayDeque<TreeNode>();
        queue.add(root);
​
        while (!queue.isEmpty()) {
            int levelNum = queue.size();
            List<Integer> subList = new LinkedList<Integer>();
            for (int i = 0; i < levelNum; i++) {
                if (queue.peek().left != null) queue.offer(queue.peek().left);
                if (queue.peek().right != null) queue.offer(queue.peek().right);
                subList.add(queue.poll().val);
            }
            list.add(0, subList);
        }
        return list;
​
    }

題目5: 編寫迭代器,返回二叉搜索樹中最小的值

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章