|
1 | 1 | [TOC] |
2 | | -# 1 二叉树的递归套路 |
| 2 | +# 1 二叉树的递归解法 |
3 | 3 |
|
4 | 4 | 1、 可以解决面试中的绝大部分二叉树(95%以上)的问题,尤其是树形dp问题 |
5 | 5 |
|
6 | 6 | 2、 其本质是利用递归遍历二叉树的便利性,每个节点在递归的过程中可以回到该节点3次 |
7 | 7 |
|
8 | 8 |
|
9 | | -==具体步骤为:== |
10 | | - |
| 9 | +具体步骤为: |
11 | 10 | 1. 假设以X节点为头,假设可以向X左树和右树要任何信息 |
12 | 11 | 2. 在上一步的假设下,讨论以X为头结点的树,得到答案的可能性(最重要),常见分类是与X无关的答案,与X有关的答案 |
13 | 12 | 3. 列出所有可能性后,确定到底需要向左树和右树要什么样的信息 |
14 | 13 | 4. 把左树信息和右树信息求全集,就是任何一颗子树都需要返回的信息S |
15 | 14 | 5. 递归函数都返回S,每颗子树都这么要求 |
16 | 15 | 6. 写代码,在代码中考虑如何把左树信息和右树信息整合出整棵树的信息 |
17 | 16 |
|
18 | | -## 1.1 二叉树的递归套路深度实践 |
| 17 | +## 1.1 二叉树的递归解法实操 |
19 | 18 |
|
20 | 19 | ### 1.1.1 例一:判断二叉树平衡与否 |
21 | 20 |
|
|
27 | 26 |
|
28 | 27 | > 所以该题,我们X需要向左右子树要的信息为,1.高度 2. 是否平衡 |
29 | 28 |
|
30 | | -```Java |
31 | | -package class08; |
32 | | - |
33 | | -public class Code01_IsBalanced { |
34 | | - |
35 | | - public static class Node { |
36 | | - public int value; |
37 | | - public Node left; |
38 | | - public Node right; |
39 | | - |
40 | | - public Node(int data) { |
41 | | - this.value = data; |
42 | | - } |
43 | | - } |
44 | | - |
45 | | - public static boolean isBalanced1(Node head) { |
46 | | - boolean[] ans = new boolean[1]; |
47 | | - ans[0] = true; |
48 | | - process1(head, ans); |
49 | | - return ans[0]; |
50 | | - } |
51 | | - |
52 | | - public static int process1(Node head, boolean[] ans) { |
53 | | - if (!ans[0] || head == null) { |
54 | | - return -1; |
55 | | - } |
56 | | - int leftHeight = process1(head.left, ans); |
57 | | - int rightHeight = process1(head.right, ans); |
58 | | - if (Math.abs(leftHeight - rightHeight) > 1) { |
59 | | - ans[0] = false; |
60 | | - } |
61 | | - return Math.max(leftHeight, rightHeight) + 1; |
62 | | - } |
63 | | - |
64 | | - public static boolean isBalanced2(Node head) { |
65 | | - return process2(head).isBalaced; |
66 | | - } |
67 | | - |
68 | | - // 左、右要求一样,Info 表示信息返回的结构体 |
69 | | - public static class Info { |
70 | | - // 是否平衡 |
71 | | - public boolean isBalaced; |
72 | | - // 高度多少 |
73 | | - public int height; |
| 29 | +```Go |
| 30 | +package main |
74 | 31 |
|
75 | | - public Info(boolean b, int h) { |
76 | | - isBalaced = b; |
77 | | - height = h; |
78 | | - } |
79 | | - } |
| 32 | +import "math" |
80 | 33 |
|
81 | | - // 递归调用,X自身也要返回信息Info。 |
82 | | - // 解决X节点(当前节点)怎么返回Info信息 |
83 | | - public static Info process2(Node X) { |
84 | | - // base case |
85 | | - if (X == null) { |
86 | | - return new Info(true, 0); |
87 | | - } |
88 | | - // 得到左树信息 |
89 | | - Info leftInfo = process2(X.left); |
90 | | - // 得到右树信息 |
91 | | - Info rightInfo = process2(X.right); |
92 | | - |
93 | | - // 高度等于左右最大高度,加上当前头结点的高度1 |
94 | | - int height = Math.max(leftInfo.height, rightInfo.height) + 1; |
95 | | - boolean isBalanced = true; |
96 | | - // 左树不平衡或者右树不平衡,或者左右两子树高度差超过1 |
97 | | - // 那么当前节点为头的树,不平衡 |
98 | | - if (!leftInfo.isBalaced || !rightInfo.isBalaced || Math.abs(leftInfo.height - rightInfo.height) > 1) { |
99 | | - isBalanced = false; |
100 | | - } |
101 | | - // 加工出当前节点的信息返回 |
102 | | - return new Info(isBalanced, height); |
103 | | - } |
| 34 | +type Node struct { |
| 35 | + Val int |
| 36 | + Left *Node |
| 37 | + Right *Node |
| 38 | +} |
104 | 39 |
|
105 | | - // for test |
106 | | - public static Node generateRandomBST(int maxLevel, int maxValue) { |
107 | | - return generate(1, maxLevel, maxValue); |
108 | | - } |
| 40 | +// BalanceInfo 表示递归过程中需要收集每个节点的信息 |
| 41 | +type BalanceInfo struct { |
| 42 | + // 当前节点为头的树是不是平衡的 |
| 43 | + IsBalanced bool |
| 44 | + // 当前节点为头的树的高度是多少 |
| 45 | + Height int |
| 46 | +} |
109 | 47 |
|
110 | | - // for test |
111 | | - public static Node generate(int level, int maxLevel, int maxValue) { |
112 | | - if (level > maxLevel || Math.random() < 0.5) { |
113 | | - return null; |
114 | | - } |
115 | | - Node head = new Node((int) (Math.random() * maxValue)); |
116 | | - head.left = generate(level + 1, maxLevel, maxValue); |
117 | | - head.right = generate(level + 1, maxLevel, maxValue); |
118 | | - return head; |
119 | | - } |
| 48 | +// IsBalanced 给定二叉树头节点,判断该二叉树是不是平衡二叉树 |
| 49 | +func (head *Node) IsBalanced() bool { |
| 50 | + return Process(head).IsBalanced |
| 51 | +} |
120 | 52 |
|
121 | | - public static void main(String[] args) { |
122 | | - int maxLevel = 5; |
123 | | - int maxValue = 100; |
124 | | - int testTimes = 1000000; |
125 | | - for (int i = 0; i < testTimes; i++) { |
126 | | - Node head = generateRandomBST(maxLevel, maxValue); |
127 | | - if (isBalanced1(head) != isBalanced2(head)) { |
128 | | - System.out.println("Oops!"); |
129 | | - } |
130 | | - } |
131 | | - System.out.println("finish!"); |
| 53 | +func Process(node *Node) *BalanceInfo { |
| 54 | + if node == nil { |
| 55 | + return &BalanceInfo{ |
| 56 | + IsBalanced: true, |
| 57 | + Height: 0, |
| 58 | + } |
| 59 | + } |
| 60 | + // 左子树信息 |
| 61 | + leftInfo := Process(node.Left) |
| 62 | + // 右子树信息 |
| 63 | + rightInfo := Process(node.Right) |
| 64 | + // 高度等于左右最大高度,加上当前头结点的高度1 |
| 65 | + curHeight := int(math.Max(float64(leftInfo.Height), float64(rightInfo.Height))) + 1 |
| 66 | + curIsBalanced := true |
| 67 | + // 左树不平衡或者右树不平衡,或者左右两子树高度差超过1 |
| 68 | + // 那么当前节点为头的树,不平衡 |
| 69 | + if !leftInfo.IsBalanced || !rightInfo.IsBalanced || math.Abs(float64(leftInfo.Height) -float64(rightInfo.Height)) > 1 { |
| 70 | + curIsBalanced = false |
| 71 | + } |
| 72 | + // 加工出当前节点的信息返回 |
| 73 | + return &BalanceInfo{ |
| 74 | + IsBalanced: curIsBalanced, |
| 75 | + Height: curHeight, |
132 | 76 | } |
133 | | - |
134 | 77 | } |
135 | | - |
136 | 78 | ``` |
137 | 79 |
|
138 | 80 | ### .1.2 例二:返回二叉树任意两个节点最大值 |
|
0 commit comments