二叉树和递归
二叉树天然的递归结构
满二叉树
二叉树的前序遍历 递归实现
1void preOrder(TreeNode node){
2 if(node==null){
3 return; // 递归终止条件
4 }
5 System.out.print(node.val);
6 preOrder(node.left); // 递归过程
7 preOrder(node.right);
8}
二叉树的定义:空是一棵二叉树
二叉树总是否包含某个key
1boolean contain(TreeNode node, Key key){
2 if(node == null){
3 return false;
4 }
5 if(key == node.key){
6 return true;
7 }
8 if(contain(node.left,key)|| contain(node.right, key)){
9 return true;
10 }
11 return false;
12}
1// c++ 释放二叉树的内存
2void destory(TreeNode node){
3 if(node == null){
4 return;
5 }
6 destory(node.left);
7 destory(node.right);
8 delete node;
9 count--
10}
LeetCode 104: Maximum Depth of Binary Tree
求一棵二叉树的最高深度,从根节点到叶子节点的最长路径长度
递归实现
1public static int maxDepth(TreeNode root){
2 if(root == NULL){
3 return 0;
4 }
5 return Math.max(maxDepth(root.left), maxDepth(root.right))+1;
6}
非递归实现
1class Solution {
2 public int maxDepth(TreeNode root) {
3 Queue<Pair<TreeNode, Integer>> stack = new LinkedList<>();
4 if (root != null) {
5 stack.add(new Pair(root, 1));
6 }
7
8 int depth = 0;
9 while (!stack.isEmpty()) {
10 Pair<TreeNode, Integer> current = stack.poll();
11 root = current.getKey();
12 int current_depth = current.getValue();
13 if (root != null) {
14 depth = Math.max(depth, current_depth);
15 stack.add(new Pair(root.left, current_depth + 1));
16 stack.add(new Pair(root.right, current_depth + 1));
17 }
18 }
19 return depth;
20 }
21};
复习二叉树相关的所有操作
LeetCode 111:Minimum Depth of Binary Tree
求一棵二叉树的最低深度,从根节点到叶子节点的最短路径长度
1class Solution {
2 public int minDepth(TreeNode root) {
3 if (root == null) {
4 return 0;
5 }
6
7 if ((root.left == null) && (root.right == null)) {
8 return 1;
9 }
10
11 int min_depth = Integer.MAX_VALUE;
12 if (root.left != null) {
13 min_depth = Math.min(minDepth(root.left), min_depth);
14 }
15 if (root.right != null) {
16 min_depth = Math.min(minDepth(root.right), min_depth);
17 }
18
19 return min_depth + 1;
20 }
21}
一个简单的二叉树问题引发的血案
226: Invert Binary Tree
反转一棵二叉树
Max Howell 因为不会做这道题目而被Google拒绝
Google:90%of our engineer use the software you wrote(Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
1public TreeNode invertTree(TreeNode root) {
2 if (root == null) {
3 return null;
4 }
5 TreeNode right = invertTree(root.right);
6 TreeNode left = invertTree(root.left);
7 root.left = right;
8 root.right = left;
9 return root;
10}
100: Same Tree
给出两棵二叉树,判断这两棵二叉树是否完全一样
1 public boolean isSameTree(TreeNode p, TreeNode q) {
2 // p and q are both null
3 if (p == null && q == null) return true;
4 // one of p and q is null
5 if (q == null || p == null) return false;
6 if (p.val != q.val) return false;
7 return isSameTree(p.right, q.right) &&
8 isSameTree(p.left, q.left);
9 }
101: Sysmmetric Tree
给出一棵二叉树,判断其是否是左右对称的
1public boolean isSymmetric(TreeNode root) {
2 return isMirror(root, root);
3}
4
5public boolean isMirror(TreeNode t1, TreeNode t2) {
6 if (t1 == null && t2 == null) return true;
7 if (t1 == null || t2 == null) return false;
8 return (t1.val == t2.val)
9 && isMirror(t1.right, t2.left)
10 && isMirror(t1.left, t2.right);
11}
222: Count Complete Tree Node
给定一个棵完全二叉树,求完全二叉树节点的个数
完全二叉树: 除了最后一层,所有层的节点数达到最大,与此同时,最后一层的所有节点都在最左侧。 堆使用完全二叉树。
满二叉树: 所有层的节点数达到最大。
1 public int countNodes(TreeNode root) {
2 if(root == null){
3 return 0;
4 }
5 int left = countLevel(root.left);
6 int right = countLevel(root.right);
7 if(left == right){
8 return countNodes(root.right) + (1<<left);
9 }else{
10 return countNodes(root.left) + (1<<right);
11 }
12 }
13 private int countLevel(TreeNode root){
14 int level = 0;
15 while(root != null){
16 level++;
17 root = root.left;
18 }
19 return level;
20 }
110 : Balanced Binary Tree
判断一棵树是否为平衡二叉树
平衡二叉树: 每一个节点的左右子树的高度差不超过1
1public boolean isBalanced(TreeNode root) {
2 //它是一棵空树
3 if (root == null) {
4 return true;
5 }
6 //它的左右两个子树的高度差的绝对值不超过1
7 int leftDepth = getTreeDepth(root.left);
8 int rightDepth = getTreeDepth(root.right);
9 if (Math.abs(leftDepth - rightDepth) > 1) {
10 return false;
11 }
12 //左右两个子树都是一棵平衡二叉树
13 return isBalanced(root.left) && isBalanced(root.right);
14
15}
16
17private int getTreeDepth(TreeNode root) {
18 if (root == null) {
19 return 0;
20 }
21 int leftDepth = getTreeDepth(root.left);
22 int rightDepth = getTreeDepth(root.right);
23 return Math.max(leftDepth, rightDepth) + 1;
24}
注意递归的终止条件
112: Path sum
给出一棵二叉树以及一个数字sum, 判断这棵二叉树上是否存在一条从根到叶子的路径。其路径上所有节点和为sum。
易错情况
1public static boolean hasPathSum(TreeNode root, int sum){
2 if( root == null){ // 递归终止条件有问题
3 return sum == 0;
4 }
5 if(hasPathSum(root.left, sum -root.val)){
6 return true;
7 }
8 if(hasPathSum(root.right, sum -root.val)){
9 return true;
10 }
11 return false;
12}
1public static boolean hasPathSum(TreeNode root, int sum){
2 if(root == null){
3 return false;
4 }
5 if( root.left == null && root.right = null){ // 递归终止条件有问题
6 return sum == root.val;
7 }
8 if(hasPathSum(root.left, sum -root.val)){
9 return true;
10 }
11 if(hasPathSum(root.right, sum -root.val)){
12 return true;
13 }
14 return false;
15 // return hasPathSum(root.left, sum -root.val)||hasPathSum(root.right, sum -root.val);
16}
404:Sum of Left Leaves
求出一棵二叉树所有左叶子的和
1public int sumOfLeftLeaves(TreeNode root) {
2 if (root == null) return 0;
3 if (root.left == null) return sumOfLeftLeaves(root.right); //如果左子树为空,那么只需返回右子树的左叶子和
4 if (root.left.left == null && root.left.right == null) // 如果左子树为叶子节点,那么需返回右子树的左叶子和 + 左孩子的值
5 return sumOfLeftLeaves(root.right) + root.left.val;
6 return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right); // 其他情况需返回左右子树的左叶子和之和
7}
257: Binary Tree Path
给定一棵二叉树,返回所有表示从根节点到叶子节点路径的字符串
1 public List<String> binaryTreePaths(TreeNode root) {
2 List<String> list = new ArrayList<>();
3 if(root == null){
4 return list;
5 }
6 if(root.left == null && root.right == null){
7 list.add(""+root.val);
8 }
9 List<String> left = binaryTreePaths(root.left);
10 for(String str: left){
11 list.add(""+root.val+"->"+str);
12 }
13 List<String> right = binaryTreePaths(root.right);
14 for(String str: right){
15 list.add(""+root.val+"->"+str);
16 }
17 return list;
18 }
113:Path Sum II
给定一棵二叉树,返回所有从根节点到叶子节点的路径,其和为sum
对于右侧二叉树,sum = 22,结果为[[5,4,11,2],[5,4,8,5]]
129:Sum root to Leaf Numbers
给定一棵二叉树,每个节点只包含数字0-9,从根节点到叶子节点的每条路径可以表示成一个数,求这些数的和。
更复杂的递归逻辑
437: Path Sum II
给出一棵二叉树以及一个数字sum,判断在这棵二叉树上存在多少条路径,其路径上所有节点和为sum。
- 其中路径不一定哟啊起始于根节点;终止于叶子节点
- 路径可以从任意节点开始,但是只能是向下走的。