有關樹的算法題小結
: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: 編寫迭代器,返回二叉搜索樹中最小的值