有关树的算法题小结
: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: 编写迭代器,返回二叉搜索树中最小的值