基础篇
前序遍历
144. 二叉树的前序遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree1.Right = tree2
tree2.Left = tree3
r := preorderTraversal(tree1)
fmt.Println(r) // [1 2 3]
}
func preorderTraversal(root *TreeNode) []int {
// ......
}
|
【拓展】如何 不使用递归 来完成二叉树的前序遍历呢?
答案
思路:
对二叉树进行递归遍历,需要从以下 3 个方面入手:
1.递归终止条件:root结点为nil
2.本轮递归需要做的事情:先遍历中,再遍历左,最后遍历右
3.返回值:无
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 前序遍历函数
func preorderTraversal(root *TreeNode) []int {
var result []int
traversal(root, &result) // 为了让traversal函数中对result的append操作同步到本函数中,这里需要传切片的地址
return result
}
func traversal(node *TreeNode, result *[]int) {
if node == nil { // 确定递归的出口
return
}
// 先将当前节点的值加入结果列表
*result = append(*result, node.Val)
// 然后递归遍历左子树
traversal(node.Left, result)
// 最后递归遍历右子树
traversal(node.Right, result)
}
|
非递归实现:
思路:我们可以使用栈来完成这一操作,先将 root 结点入栈,然后一个循环(循环条件为栈不为空)
当栈不为空的时候,把栈中元素弹出,放入到目标数组result中,然后将右结点和左结点依次放入栈中。
由于先序遍历是 中左右 的顺序,而栈是 先入后出,所以入栈是需要先将右结点入栈,然后将左结点入栈。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
func preorderTraversal(root *TreeNode) []int {
stack := make(map[int]*TreeNode) // map模拟栈
result := make([]int, 0)
stack[0] = root
for len(stack) != 0 {
topNode := stack[len(stack)-1]
delete(stack, len(stack)-1)
if topNode != nil {
result = append(result, topNode.Val)
} else {
continue
}
stack[len(stack)] = topNode.Right
stack[len(stack)] = topNode.Left
}
return result
}
|
中序遍历
94. 二叉树的中序遍历
1
2
3
4
5
6
7
8
9
10
11
12
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree1.Right = tree2
tree2.Left = tree3
r := inorderTraversal(tree1)
fmt.Println(r) // [1 3 2]
}
func inorderTraversal(root *TreeNode) []int {
// ......
}
|
答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
func inorderTraversal(root *TreeNode) []int {
result := make([]int, 0)
traversal(root, &result) // 这里要传地址
return result
}
// 中序遍历:左中右
func traversal(root *TreeNode, result *[]int) {
if root == nil {
return
}
traversal(root.Left, result)
*result = append(*result, root.Val)
traversal(root.Right, result)
}
|
后序遍历
145. 二叉树的后序遍历
1
2
3
4
5
6
7
8
9
10
11
12
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree1.Right = tree2
tree2.Left = tree3
r := postorderTraversal(tree1)
fmt.Println(r) // [3 2 1]
}
func postorderTraversal(root *TreeNode) []int {
// ......
}
|
答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
func postorderTraversal(root *TreeNode) []int {
result := make([]int, 0)
traversal(root, &result) // 这里要传地址
return result
}
// 后序遍历:左右中
func traversal(root *TreeNode, result *[]int) {
if root == nil {
return
}
traversal(root.Left, result)
traversal(root.Right, result)
*result = append(*result, root.Val)
}
|
层序遍历
102. 二叉树的层序遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := levelOrder(tree1)
fmt.Println(r) // [[1] [2 3] [4 5]]
}
func levelOrder(root *TreeNode) [][]int {
// ......
}
|
答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
func levelOrder(root *TreeNode) [][]int {
if root == nil {
return nil
}
queue := make([]*TreeNode, 1)
layerItem := make([]int, 0)
result := make([][]int, 0)
queue[0] = root
for len(queue) != 0 {
size := len(queue) // 记录每层的元素个数
layerItem = []int{}
for size > 0 {
layerItem = append(layerItem, queue[0].Val) // 将队首元素加入到layerItem中
if queue[0].Left != nil {
queue = append(queue, queue[0].Left)
}
if queue[0].Right != nil {
queue = append(queue, queue[0].Right)
}
queue = queue[1:] // 去掉队首元素
size--
}
result = append(result, layerItem)
}
return result
}
|
二叉树的右视图
199. 二叉树的右视图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := rightSideView(tree1)
fmt.Println(r) // [1, 3, 5]
}
func rightSideView(root *TreeNode) []int {
// ......
}
|
答案
思路:将每一层的最后一个元素添加到 result 数组中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
func rightSideView(root *TreeNode) []int {
if root == nil {
return nil
}
result := make([]int, 0)
queue := make([]*TreeNode, 1)
queue[0] = root
for len(queue) != 0 {
size := len(queue)
for size > 0 {
if size == 1 {
result = append(result, queue[0].Val) // 将每层最后一个元素加入到result
}
if queue[0].Left != nil {
queue = append(queue, queue[0].Left)
}
if queue[0].Right != nil {
queue = append(queue, queue[0].Right)
}
queue = queue[1:] // 弹出队首元素
size--
}
}
return result
}
|
N叉树的层序遍历
429. N 叉树的层序遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
type Node struct {
Val int
Children []*Node
}
func main() {
node1 := &Node{1, nil}
node2 := &Node{2, nil}
node3 := &Node{3, nil}
node4 := &Node{4, nil}
node5 := &Node{5, nil}
node6 := &Node{6, nil}
node1.Children = []*Node{node2, node3, node4}
node2.Children = []*Node{node5, node6}
r := levelOrder(node1)
fmt.Println(r) // [[1] [2 3 4] [5 6]]
}
func levelOrder(root *Node) [][]int {
// ......
}
|
答案
定义size,统计每层元素的个数。
将root加入到队列中,当队列不为空时,取出队列的首元素,放到layerItem中
将首元素的所有孩子结点加入队列。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
func levelOrder(root *Node) [][]int {
if root == nil {
return nil
}
queue := make([]*Node, 1)
result := make([][]int, 0)
layerItem := make([]int, 0)
queue[0] = root
for len(queue) != 0 {
layerItem = []int{}
size := len(queue)
for size > 0 {
layerItem = append(layerItem, queue[0].Val)
if queue[0].Children != nil {
queue = append(queue, queue[0].Children...)
}
queue = queue[1:]
size--
}
result = append(result, layerItem)
}
return result
}
|
二叉树的最大深度
104. 二叉树的最大深度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := maxDepth(tree1)
fmt.Println(r) // 3
}
func maxDepth(root *TreeNode) int {
// ......
}
|
答案
递归,先找左子树的深度,然后找有子树的深度,最后求最大值
1
2
3
4
5
6
|
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
return max(maxDepth(root.Left), maxDepth(root.Right)) + 1
}
|
二叉树的最小深度
111. 二叉树的最小深度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := minDepth(tree1)
fmt.Println(r) // 2
}
func minDepth(root *TreeNode) int {
// ......
}
|
答案
1
2
3
4
5
6
7
8
9
10
11
|
func minDepth(root *TreeNode) int {
if root == nil {
return 0
}
left := minDepth(root.Left)
right := minDepth(root.Right)
if left == 0 || right == 0 { // 注意处理单边二叉树的问题
return max(left, right) + 1
}
return min(left, right) + 1
}
|
翻转二叉树
226. 翻转二叉树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
func invertTree(root *TreeNode) *TreeNode {
//......
}
func main() {
// 4
// / \
// 2 7
// / \ / \
// 1 3 6 9
root := &TreeNode{Val: 4}
root.Left = &TreeNode{Val: 2}
root.Right = &TreeNode{Val: 7}
root.Left.Left = &TreeNode{Val: 1}
root.Left.Right = &TreeNode{Val: 3}
root.Right.Left = &TreeNode{Val: 6}
root.Right.Right = &TreeNode{Val: 9}
// 翻转树
invertedRoot := invertTree(root)
// 层序打印翻转后的树
fmt.Println(invertedRoot.Val, "\n",
invertedRoot.Left.Val, invertedRoot.Right.Val, "\n",
invertedRoot.Left.Left.Val, invertedRoot.Left.Right.Val,
invertedRoot.Right.Left.Val, invertedRoot.Right.Right.Val)
// 4
// 7 2
// 9 6 3 1
}
|
答案
将二叉树左子树和右子树进行交换。
1
2
3
4
5
6
7
8
9
|
func invertTree(root *TreeNode) *TreeNode {
if root == nil {
return root
}
root.Left, root.Right = root.Right, root.Left
invertTree(root.Left)
invertTree(root.Right)
return root
}
|
对称二叉树
101. 对称二叉树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{2, nil, nil}
tree4 := &TreeNode{3, nil, nil}
tree5 := &TreeNode{4, nil, nil}
tree6 := &TreeNode{4, nil, nil}
tree7 := &TreeNode{3, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
tree3.Left = tree6
tree3.Right = tree7
r := isSymmetric(tree1)
fmt.Println(r) // true
}
func isSymmetric(root *TreeNode) bool {
// ......
}
|
答案
思路:
先明确本题只能使用后序遍历,因为我们需要搜集左右孩子的信息,进行比较。
现在需要确定递归的3个条件:递归的结束条件、本次递归需要做的事情,本次递归的返回值。
递归的结束条件:也就是这里可以直接得出结果的条件,具体如下:
- 左空,右非空—-false
- 右空,左非空—-false
- 左空,右空—-true
- 左非空,右非空,但值不相等—-false
剩下的一个条件就是左右不为空,且值相等的情况,这就是我们继续向下一层递归的条件。
下一层递归的条件(也就是本次递归需要做的事情)
如果 左结点的右孩子==右结点的左孩子,且左结点的左孩子==右结点的右孩子,那么继续往下一层进行比较。
本次递归的返回值:左右结点是否相等(这里的相等指的是是否对称)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func isSymmetric(root *TreeNode) bool {
if root == nil {
return true
}
return compare(root.Left, root.Right)
}
func compare(left, right *TreeNode) bool {
if left == nil && right != nil { // 把判空条件写在前面,防止后面出现空指针异常
return false
} else if left != nil && right == nil {
return false
} else if left == nil && right == nil {
return true
} else if left.Val != right.Val { // 这里left不可能为空指针
return false
} else { // 左右都不为空的情况,应该递归调用compare函数,比较左右孩子是否对称
// 左结点的左孩子 vs 右结点的右孩子 && 左结点的右孩子 vs 右结点的左孩子
return compare(left.Left, right.Right) && compare(left.Right, right.Left)
}
}
|
完全二叉树的节点个数
222. 完全二叉树的节点个数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree6 := &TreeNode{6, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
tree3.Left = tree6
r := countNodes(tree1)
fmt.Println(r) // 6
}
func countNodes(root *TreeNode) int {
// ......
}
|
答案
方法1: 遍历所有结点(这里采用后序遍历)
1
2
3
4
5
6
|
func countNodes(root *TreeNode) int {
if root == nil {
return 0
}
return countNodes(root.Left) + countNodes(root.Right) + 1
}
|
方法2: 利用完全二叉树的性质:如果右结点不为空,那么左结点也一定不为空。
我们可以判断某子二叉树是否是满二叉树,如果是满二叉树,那我们可以根据二叉树的深度直接计算出该二叉树的节点数量。
即:nodeCount=2^depth-1
如何判断是否为满二叉树呢?一个指针一直向左遍历,另一个指针一直向右遍历,如果左指针的深度等于右指针的深度,说明该二叉树为满二叉树。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
func countNodes(root *TreeNode) int {
if root == nil {
return 0
}
left := root.Left
right := root.Right
leftDepth := 0
rightDepth := 0
for left != nil {
left = left.Left
leftDepth++
}
for right != nil {
right = right.Right
rightDepth++
}
if leftDepth == rightDepth { // 是满二叉树
return 2<<leftDepth - 1 // 使用左移来实现乘方的效果
}
return countNodes(root.Left) + countNodes(root.Right) + 1
}
|
平衡二叉树
110. 平衡二叉树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{2, nil, nil}
tree4 := &TreeNode{3, nil, nil}
tree5 := &TreeNode{4, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := isBalanced(tree1)
fmt.Println(r) // true
}
func isBalanced(root *TreeNode) bool {
// ......
}
|
答案
使用后序遍历,先计算左结点的“深度”,再计算右结点的“深度”,然后计算左右结点的深度差是否大于1。
这里的深度指的是最深结点的层数(从1开始),但如果左右结点的深度超过1了,我们直接用返回-1(用-1来向上层标识是否合法,如果不合法我们直接就返回false了,不需要再对左右的深度差进行判断)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
func isBalanced(root *TreeNode) bool {
if root == nil {
return true
}
if treeDepth(root.Left) == -1 || treeDepth(root.Right) == -1 { // 注意这里添加这个条件
return false
}
if math.Abs(float64(treeDepth(root.Left)-treeDepth(root.Right))) > 1 {
return false
}
return true
}
func treeDepth(root *TreeNode) int {
if root == nil {
return 0
}
lDepth := treeDepth(root.Left)
if lDepth == -1 {
return -1
}
rDepth := treeDepth(root.Right)
if rDepth == -1 {
return -1
}
if math.Abs(float64(lDepth-rDepth)) > 1 {
return -1
} else {
return max(lDepth, rDepth) + 1
}
}
|
二叉树的所有路径
257. 二叉树的所有路径
本题较为复杂,可以多加练习。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := binaryTreePaths(tree1)
fmt.Println(r) // [1->2 1->3->4 1->3->5]
}
func binaryTreePaths(root *TreeNode) []string {
// ......
}
|
答案
本题使用前序遍历(深度优先),当某条分支遍历完之后,在向上进行回溯。如下图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
func binaryTreePaths(root *TreeNode) []string {
res := make([]string, 0)
var travel func(node *TreeNode, s string)
travel = func(node *TreeNode, s string) {
if node.Left == nil && node.Right == nil { // 递归出口:node为叶子结点
v := s + strconv.Itoa(node.Val) // 叶子结点的值也需要加上,而且后面不加"->"
res = append(res, v)
return // 遇到叶子结点时,需要进行回溯,直接向上层递归返回
}
// 这里是前序遍历(深度优先遍历),中右左
s = s + strconv.Itoa(node.Val) + "->" // s表示当前已经遍历过的路径
if node.Left != nil { // 左结点不为空,继续遍历左结点
travel(node.Left, s) // 递归遍历node的左孩子
}
if node.Right != nil { // 右结点不为空,继续遍历右结点
travel(node.Right, s)
}
}
travel(root, "") //
return res
}
|
左叶子之和
404. 左叶子之和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := sumOfLeftLeaves(tree1)
fmt.Println(r) // 6
}
func sumOfLeftLeaves(root *TreeNode) int {
// ......
}
|
答案
递归实现,采用后序遍历的方式(左右中)。
确定递归的出口:node 为空,或者 root 的左右孩子为空。
本轮递归需要做的事情:获取 node 左孩子的 sum,获取右孩子的 sum,将二者求和。
递归的返回值:sum。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func sumOfLeftLeaves(root *TreeNode) int {
if root == nil {
return 0
}
// 只递归到非叶子结点(因为非叶子节点才能确定它的左孩子)
// 我们无法通过某个几点判断它是左孩子还是右孩子,所以递归到叶子结点也没有意义
if root.Left == nil && root.Right == nil {
return 0
}
lSum := sumOfLeftLeaves(root.Left)
rSum := sumOfLeftLeaves(root.Right)
if root.Left != nil && root.Left.Left == nil && root.Left.Right == nil {
lSum = root.Left.Val // 这里只是记录目标值,不做任何返回,以实现下次递归的复用
}
return lSum + rSum
}
|
找树左下角的值
513. 找树左下角的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := findBottomLeftValue(tree1)
fmt.Println(r) // 4
}
func findBottomLeftValue(root *TreeNode) int {
// ......
}
|
答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
func findBottomLeftValue(root *TreeNode) int {
maxDepth := -1
target := 0
var traversal = func(node *TreeNode, depth int) {}
traversal = func(node *TreeNode, depth int) {
if node.Left == nil && node.Right == nil {
if depth > maxDepth {
maxDepth = depth
target = node.Val
}
}
if node.Left != nil {
traversal(node.Left, depth+1)
// 这里将回溯的过程隐藏在了第二个参数里面
// 也就是往后递归一层的时候,depth加1了,但这个加1操作只对下层的递归有效,
// 当回溯到本层的时候,depth值是不变的
}
if node.Right != nil {
traversal(node.Right, depth+1)
}
}
traversal(root, 1)
return target
}
|
进阶篇
路径总和
112. 路径总和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := hasPathSum(tree1, 8)
fmt.Println(r) // true
}
func hasPathSum(root *TreeNode, targetSum int) bool {
// ......
}
|
答案
本题和二叉树的所有路径差不多,也是使用前序遍历,即:中左右。
确定递归的出口:node 的左右结点都为空(node 为叶子结点)
确定本次递归需要做的事情:如果 node 的左结点不为空,遍历左结点,如果 node 的右结点不为空,遍历右结点
递归的返回值:是否满足条件的布尔值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
func hasPathSum(root *TreeNode, targetSum int) bool {
if root == nil {
return false
}
var traversal func(node *TreeNode, sum int) bool
traversal = func(node *TreeNode, sum int) bool {
if node.Left == nil && node.Right == nil {
if targetSum == sum+node.Val {
return true // 向上层返回true
}
}
sum += node.Val
if node.Left != nil {
// 当某层递归返回true时,直接向上层返回true,否则不做返回,继续递归
// 注意:这不能直接写成 return traversal(node.Left, sum)
if traversal(node.Left, sum) {
return true
}
}
if node.Right != nil {
if traversal(node.Right, sum) {
return true
}
}
return false
}
return traversal(root, 0)
}
|
从中序与后序遍历序列构造二叉树
本题较为复杂,暂时跳过。
106. 从中序与后序遍历序列构造二叉树
最大二叉树
654. 最大二叉树
1
2
3
4
5
6
7
8
|
func main() {
nums := []int{3, 2, 1, 6, 0, 5}
r := constructMaximumBinaryTree(nums)
fmt.Println(r)
}
func constructMaximumBinaryTree(nums []int) *TreeNode {
// ......
}
|
答案
构造二叉树,我们都需要使用前序遍历。
确定递归的出口:nums 只有1个元素,直接返回用该元素构造的结点。
确定本次递归需要做的事情:先找出最大值和最大值所在的下标,用最大值将原数组进行分隔,对左右数组分别调用 constructMaximumBinaryTree(区间需要统一为左闭右开)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
func constructMaximumBinaryTree(nums []int) *TreeNode {
if nums == nil {
return nil
}
if len(nums) == 1 {
return &TreeNode{nums[0], nil, nil}
}
maxVal := nums[0]
maxIndex := 0
for i := 1; i < len(nums); i++ {
if nums[i] > maxVal {
maxVal = nums[i]
maxIndex = i
}
}
curNode := &TreeNode{maxVal, nil, nil} // 中
if maxIndex > 0 {
curNode.Left = constructMaximumBinaryTree(nums[0:maxIndex]) // 左闭右开区间
}
if maxIndex < len(nums)-1 {
curNode.Right = constructMaximumBinaryTree(nums[maxIndex+1:])
}
return curNode
}
|
合并二叉树
617. 合并二叉树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
func main() {
node11 := &TreeNode{1, nil, nil}
node12 := &TreeNode{2, nil, nil}
node13 := &TreeNode{3, nil, nil}
node21 := &TreeNode{4, nil, nil}
node22 := &TreeNode{5, nil, nil}
node23 := &TreeNode{6, nil, nil}
node11.Left = node12
node11.Right = node13
node21.Left = node22
node21.Right = node23
r := mergeTrees(node11, node21)
fmt.Println(r) // &{5 0xc000008060 0xc000008078}
}
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
// ......
}
|
答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
// 构造二叉树我们都使用前序遍历(中左右)
// 递归出口
if root1 == nil { // 这里也包含了root1和root2同时为空的情况,返回nil
return root2
}
if root2 == nil {
return root1
}
root1.Val = root1.Val + root2.Val // 把两个二叉树合并到root1上
root1.Left = mergeTrees(root1.Left, root2.Left)
root1.Right = mergeTrees(root1.Right, root2.Right)
return root1
}
|
二叉搜索树中的搜索
700. 二叉搜索树中的搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{4, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{7, nil, nil}
tree4 := &TreeNode{1, nil, nil}
tree5 := &TreeNode{3, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
r := searchBST(tree1, 3)
fmt.Println(r)
}
func searchBST(root *TreeNode, val int) *TreeNode {
// ......
}
|
答案
方法1:递归法
先确定递归的出口:如果 root 的值等于了 val 则返回 root,如果 root 为空,则返回 root(空)
如果 val 大于 root 的值,则向右子树搜索,否则向左子树搜索。
1
2
3
4
5
6
7
8
9
10
11
12
|
func searchBST1(root *TreeNode, val int) *TreeNode {
if root == nil || root.Val == val {
return root
}
var result *TreeNode
if val > root.Val {
result = searchBST1(root.Right, val)
} else {
result = searchBST1(root.Left, val)
}
return result
}
|
方法2:迭代法
当 root 不为空时,一直往下搜索,最后返回 root。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func searchBST2(root *TreeNode, val int) *TreeNode {
for root != nil {
if val == root.Val {
return root
}
if val > root.Val { // 往右搜索
root = root.Right
} else {
root = root.Left
}
}
return root
}
|
验证二叉搜索树
98. 验证二叉搜索树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{5, nil, nil}
tree2 := &TreeNode{4, nil, nil}
tree3 := &TreeNode{6, nil, nil}
tree4 := &TreeNode{3, nil, nil}
tree5 := &TreeNode{7, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := isValidBST(tree1)
fmt.Println(r) // false
}
func isValidBST(root *TreeNode) bool {
// ......
}
|
答案
思路1:我们可能会这样想,采用后序遍历,先分别判断左右子树是否是平衡二叉树(左右子树为空返回true),如果是的话,再分四种情况进行讨论:
- 如果左右都为空,返回 true;
- 如果左右都不为空,同时左右中元素依次递增的话,返回 true;
- 如果左不为空(右为空),同时左大于中,返回 true;
- 如果右不为空(左为空),同时右大于中,返回 true;
但是这样存在一个漏洞,那就是如果 root 的右孩子(right)大于 root,但 right(right 是二叉搜索树)的左孩子小于了 root,会判定 true 而不是 false,如:root = [ 5 ,4, 6, null, null, 3, 7 ]。
所以,思路1是行不通的。
观察发现,如果 root 是二叉搜索树,那么中序遍历得到的数组一定是升序的。
思路2:直接中序遍历,如果得到的数组是升序的,则返回 true。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
func isValidBST1(root *TreeNode) bool {
result := make([]int, 0)
var traversal func(node *TreeNode, result *[]int)
traversal = func(node *TreeNode, result *[]int) {
if node == nil {
return
}
traversal(node.Left, result)
*result = append(*result, node.Val)
traversal(node.Right, result)
}
traversal(root, &result)
for i := 1; i < len(result); i++ {
if result[i] <= result[i-1] { // 注意,这里等于也要返回false
return false
}
}
return true
}
|
但这样需要额外开辟数组空间。
思路3:在思路 2 的基础上进行改进,不需要额外的数组空间,在遍历时维护一个 maxVal,如果当前数值大于 maxVal,则更新 maxVal,否则返回 false。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func isValidBST2(root *TreeNode) bool {
// 由于Leetcode上面不允许定义全局变量(容易遇到不可知的错误),所以这里只能定义为局部变量,然后再定义一层函数调用
var maxVal = math.MinInt64 // 记录遍历过的最大的数值
var traversal func(root *TreeNode) bool
traversal = func(root *TreeNode) bool {
if root == nil {
return true
}
var lValid, rValid bool
lValid = traversal(root.Left) // 左
if root.Val > maxVal { // 中
maxVal = root.Val
} else {
return false
}
rValid = traversal(root.Right) // 右
return lValid && rValid
}
return traversal(root)
}
|
二叉搜索树的最小绝对差
530. 二叉搜索树的最小绝对差
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{5, nil, nil}
tree2 := &TreeNode{4, nil, nil}
tree3 := &TreeNode{7, nil, nil}
tree4 := &TreeNode{6, nil, nil}
tree5 := &TreeNode{8, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := getMinimumDifference(tree1)
fmt.Println(r) // 1
}
func getMinimumDifference(root *TreeNode) int {
// ......
}
|
答案
分析:返回二叉搜索树,任意两不同节点值之间的最小差值。
由于这是二叉搜索树,那么结点间的最小差值一定来自相邻结点之间的差值。
我们可以定义两个同步指针,一个 pre 指向当前结点的前一个结点,一个 cur 指向当前结点,两个指针同步移动。
定义 minDiff = math.MaxInt,如果 cur.Val - pre.Val 小于 minDiff,则更新 minDiff 的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
func getMinimumDifference(root *TreeNode) int {
var traversal func(node *TreeNode)
var minDiff = math.MaxInt
var pre *TreeNode
traversal = func(cur *TreeNode) {
if cur == nil {
return
}
// 中序遍历:左中右
traversal(cur.Left)
if pre != nil {
if math.Abs(float64(cur.Val-pre.Val)) < float64(minDiff) {
minDiff = int(math.Abs(float64(cur.Val - pre.Val)))
}
}
pre = cur
traversal(cur.Right)
}
traversal(root)
return minDiff
}
|
二叉搜索树中的众数
501. 二叉搜索树中的众数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
tree1 := &TreeNode{5, nil, nil}
tree2 := &TreeNode{4, nil, nil}
tree3 := &TreeNode{7, nil, nil}
tree4 := &TreeNode{7, nil, nil}
tree5 := &TreeNode{7, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree3.Left = tree4
tree3.Right = tree5
r := findMode(tree1)
fmt.Println(r) // [7]
}
func findMode(root *TreeNode) []int {
// ......
}
|
答案
也是使用两个指针 pre 和 cur,在遍历二叉树时,统计某个相同元素出现的次数 count。
pre 为 cur 的前一个结点,如果 cur 的值和 pre 的值相等,则 count++,否则 count 置1。
再定义一个 maxCount,保存整个二叉树的出现最多元素的次数,如果 count==maxCount,则将遍历到的元素加入到目标数组 result 中。
如果 count > maxCount,则将 result 设置为只有当前元素的数组(清空前面存入的数据)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
func findMode(root *TreeNode) []int {
var count = 1 // 某元素出现的次数
var maxCount = math.MinInt // 二叉树中出现最多元素的次数
var traversal func(node *TreeNode)
var pre *TreeNode
var result = make([]int, 0)
// 中序遍历
traversal = func(cur *TreeNode) {
if cur == nil {
return
}
traversal(cur.Left)
if pre != nil && pre.Val == cur.Val {
count++
} else {
count = 1
}
if count == maxCount {
result = append(result, cur.Val)
} else if count > maxCount {
maxCount = count
result = []int{}
result = append(result, cur.Val)
}
pre = cur // 将pre后移
traversal(cur.Right)
}
traversal(root)
return result
}
|
二叉树的最近公共祖先
236. 二叉树的最近公共祖先
本题较为复杂,可以多加练习。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
func main() {
tree1 := &TreeNode{1, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{3, nil, nil}
tree4 := &TreeNode{4, nil, nil}
tree5 := &TreeNode{5, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
r := lowestCommonAncestor(tree1, tree4, tree5)
fmt.Println(r) // &{2 0xc000008090 0xc0000080a8}
}
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
// ......
}
|
答案
我们要判断当前结点 node 的左、右结点是否包含 p 或 q,如果包含,则返回当前结点 node。
由于需要先遍历左右孩子结点,再向上返回,所以我们需要使用后序遍历。
遍历时,如果左不为空,右也不为空,则当前结点就是 p 和 q 的最近公共祖先。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if root == nil {
return nil
}
if root == p || root == q {
return root
}
left := lowestCommonAncestor(root.Left, p, q)
right := lowestCommonAncestor(root.Right, p, q)
if left != nil && right != nil {
return root
} else if left != nil {
return left
} else if left == nil {
return right
} else {
return nil
}
}
|
二叉搜索树的最近公共祖先
235. 二叉搜索树的最近公共祖先
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func main() {
tree1 := &TreeNode{4, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{6, nil, nil}
tree4 := &TreeNode{1, nil, nil}
tree5 := &TreeNode{3, nil, nil}
tree6 := &TreeNode{5, nil, nil}
tree7 := &TreeNode{7, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
tree3.Left = tree6
tree3.Right = tree7
r := lowestCommonAncestor(tree1, tree4, tree5)
fmt.Println(r) // &{2 0xc000008090 0xc0000080a8}
}
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
// ......
}
|
答案
递归
由于这是二叉搜索树,所以我们可以根据 p 和 q 的值,确定搜索的方向。
如果 p、q 的值都小于 root 的值,那么应该往 root 的左子树去搜索;
如果 p、q 的值都大于 root 的值,那么应该往 root 的右子树去搜索;
否则,root 就是 p、q 的最近公共祖先(这一点结论很重要)。
为什么能得到最后的结论呢?
因为:假设 q 大于 p,如果 root 继续往左子树搜索,那么 p 就被排除掉了,同理往右,q 被排除掉了,所以 p、q 的最近公共祖先就是 root。
1
2
3
4
5
6
7
8
9
10
11
12
|
func lowestCommonAncestor1(root, p, q *TreeNode) *TreeNode {
if root == nil {
return nil
}
if p.Val < root.Val && q.Val < root.Val {
return lowestCommonAncestor1(root.Left, p, q)
} else if p.Val > root.Val && q.Val > root.Val {
return lowestCommonAncestor1(root.Right, p, q)
} else {
return root
}
}
|
迭代法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
func lowestCommonAncestor2(root, p, q *TreeNode) *TreeNode {
if root == nil {
return nil
}
for root != nil {
if p.Val < root.Val && q.Val < root.Val {
root = root.Left
} else if p.Val > root.Val && q.Val > root.Val {
root = root.Right
} else {
return root
}
}
return nil
}
|
二叉搜索树中的插入操作
701. 二叉搜索树中的插入操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func main() {
tree1 := &TreeNode{4, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{6, nil, nil}
tree4 := &TreeNode{1, nil, nil}
tree5 := &TreeNode{3, nil, nil}
tree6 := &TreeNode{5, nil, nil}
tree7 := &TreeNode{7, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
tree3.Left = tree6
tree3.Right = tree7
r := insertIntoBST(tree1, 9)
fmt.Println(r) // &{4 0xc000008060 0xc000008078}
}
func insertIntoBST(root *TreeNode, val int) *TreeNode {
// ......
}
|
答案
在二叉搜索树插入结点时,我们需要明确一点,那就是:我们可以直接在叶子结点处插入结点,而不需要调整二叉搜索树的结构。
明确了这一点以后,二叉树的插入操作就变得简单了。
我们只需要根据插入的值 val 进行分支查找,当找到的结点 root 为空时,说明这就是我们应该插入的位置。
那么,如何将该位置添加到二叉树中呢?
我们可以给 traversal(遍历函数)添加一个返回值,如果我们是向左搜索,且找到了目标位置,那么 root 的左孩子就是 traversal 函数的返回值;反之,向右搜索,右孩子是 traversal 函数的返回值。
这样就把返回结点和二叉树连接起来了。
1
2
3
4
5
6
7
8
9
10
11
12
|
func insertIntoBST(root *TreeNode, val int) *TreeNode {
if root == nil { // 说明找到了插入的位置
root = &TreeNode{val, nil, nil}
return root
}
if root.Val < val { // 往右搜索
root.Right = insertIntoBST(root.Right, val)
} else { // 往左搜索
root.Left = insertIntoBST(root.Left, val)
}
return root
}
|
删除二叉搜索树中的节点
本题较为复杂,可以多加练习。
450. 删除二叉搜索树中的节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func main() {
tree1 := &TreeNode{4, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{6, nil, nil}
tree4 := &TreeNode{1, nil, nil}
tree5 := &TreeNode{3, nil, nil}
tree6 := &TreeNode{5, nil, nil}
tree7 := &TreeNode{7, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
tree3.Left = tree6
tree3.Right = tree7
r := deleteNode(tree1, 4)
fmt.Println(r) // &{6 0xc0000080c0 0xc0000080d8}
}
func deleteNode(root *TreeNode, key int) *TreeNode {
// ......
}
|
答案
删除结点时,主要分为下面 5 种情况。
1.未找到要删除的结点:返回空。
2.删除的结点为叶子结点(左右孩子为空):返回空,在递归调用的过程中,会让上一次递归的指针指向下一次递归的返回值。
这样就让当前结点的上层结点(左右指针根据具体情况决定)指向了空(相当于删除了该结点)。
3.要删除结点的左孩子为空,但右孩子不为空:返回右孩子结点(用右孩子替换当前结点)。
4.要删除结点的右孩子为空,但左孩子不为空:返回左孩子结点(用左孩子替换当前结点)。
5.要删除结点(A)的左右孩子都不为空:我们让它的右孩子(B)继位,需要找到右孩子 B 的孩子中最左侧的孩子C,让 B 的左孩子 C 的左孩子来指向删除结点 A 的左孩子 D(因为小到大的顺序为D、A(删除)、C、B(继位))
第 5 种情况是最复杂的,建议画图理解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
// 首先要明确函数的返回值是什么:删除某个结点之后的根节点
func deleteNode(root *TreeNode, key int) *TreeNode {
if root == nil {
return nil
}
if root.Val == key {
if root.Left == nil && root.Right == nil { // 叶子结点,返回nil
return nil
} else if root.Left != nil && root.Right == nil { // 左不为空,左孩子继承
return root.Left
} else if root.Right != nil && root.Left == nil { // 右不为空,右孩子继承
return root.Right
} else { // 左右都不为空
cur := root.Right // 要继承的结点
// 找到要继承结点的最左侧孩子的左侧位置(用来接收删除结点的左孩子)
// 如果cur的没有左孩子,那么不会进入for循环,就用cur的左孩子来解释删除结点的左孩子
for cur.Left != nil { // 这里要用for,找到cur的最深层、左侧的孩子结点
cur = cur.Left
}
cur.Left = root.Left // cur的左孩子等于删除结点的左孩子
return root.Right // 用右孩子去继承(跳过要删除的结点)
}
}
if key < root.Val { // 删除的值小于根节点的值,往左搜索
// 这里要用root.Left来接收删除之后的根节点,才能让数的指向连接起来
// 这里也包含向上回溯的过程
root.Left = deleteNode(root.Left, key)
}
if key > root.Val {
root.Right = deleteNode(root.Right, key)
}
return root
}
|
修剪二叉搜索树
669. 修剪二叉搜索树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func main() {
tree1 := &TreeNode{4, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{6, nil, nil}
tree4 := &TreeNode{1, nil, nil}
tree5 := &TreeNode{3, nil, nil}
tree6 := &TreeNode{5, nil, nil}
tree7 := &TreeNode{7, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
tree3.Left = tree6
tree3.Right = tree7
r := trimBST(tree1, 2, 5)
fmt.Println(r) // &{4 0xc0000080c0 0xc0000080d8}
}
func trimBST(root *TreeNode, low int, high int) *TreeNode {
// ......
}
|
答案
本题需要对二叉搜索树进行修剪,删除掉不在指定范围的结点。
函数的返回值是某子树修剪后的根结点。
当 root 为空时,直接返回 nil;
当 root 的值小于 low 时,应该往右搜索(左边全部舍弃,对右边进行修剪),但我们不能直接返回 root.Right,
而是应该递归调用裁剪函数 trimBST(),传入参数 root.Right。
因为 root.Right 的子树中也可能有不在 low 到 high 之间的结点。
当 root 的值大于 high 时,应该往左搜索(右边全部舍弃,对左边进行修剪),同理,我们不能直接返回root.Left。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func trimBST(root *TreeNode, low int, high int) *TreeNode {
if root == nil {
return nil
}
if root.Val < low { // 左侧全部舍弃,对右侧进行修剪
return trimBST(root.Right, low, high)
} else if root.Val > high { // 右侧全部舍弃,对左侧进行修剪
return trimBST(root.Left, low, high)
}
root.Left = trimBST(root.Left, low, high) // 用root.Left来接收对左子树修剪之后的结点(连接各个结点和回溯过程)
root.Right = trimBST(root.Right, low, high)
return root
}
|
将有序数组转换为二叉搜索树
108. 将有序数组转换为二叉搜索树
1
2
3
4
5
6
7
8
|
func main() {
nums := []int{-10, -3, 0, 5, 9}
r := sortedArrayToBST(nums)
fmt.Println(r) // &{0 0xc0000080c0 0xc0000080d8}
}
func sortedArrayToBST(nums []int) *TreeNode {
// ......
}
|
答案
为了保证构造的二叉树是平衡二叉树(左右高度差不超过 1),我们在构造二叉树时,应该选择最中间位置的元素作为根结点,然后对左右数组进行递归调用,从而构造完整的二叉树。
在对数组左右区间进行调整时,我们采用统一的左闭右闭区间。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func sortedArrayToBST(nums []int) *TreeNode {
//
var traversal func(nums []int, left int, right int) *TreeNode
traversal = func(nums []int, left, right int) *TreeNode {
if left > right { // 非法区间
return nil
}
// 采用前序遍历
mid := left + (right-left)>>1
root := &TreeNode{nums[mid], nil, nil}
root.Left = traversal(nums, left, mid-1) // 对左数组构建二叉树,返回构建好的头结点,让root的左孩子等于该结点
root.Right = traversal(nums, mid+1, right)
return root
}
return traversal(nums, 0, len(nums)-1)
}
|
把二叉搜索树转换为累加树
538. 把二叉搜索树转换为累加树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func main() {
tree1 := &TreeNode{4, nil, nil}
tree2 := &TreeNode{2, nil, nil}
tree3 := &TreeNode{6, nil, nil}
tree4 := &TreeNode{1, nil, nil}
tree5 := &TreeNode{3, nil, nil}
tree6 := &TreeNode{5, nil, nil}
tree7 := &TreeNode{7, nil, nil}
tree1.Left = tree2
tree1.Right = tree3
tree2.Left = tree4
tree2.Right = tree5
tree3.Left = tree6
tree3.Right = tree7
r := convertBST(tree1)
fmt.Println(r) &{22 0xc000008060 0xc000008078}
}
func convertBST(root *TreeNode) *TreeNode {
// ......
}
|
答案
由于需要把大于当前结点的值都累加到本结点中,所以我们遍历的顺序为:右中左。
右中左,就是中序遍历的逆过程。
使用 pre 指针指向当前结点 cur 的前一个结点,让当前结点的值等于 cur 的值加上 pre 的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
func convertBST(root *TreeNode) *TreeNode {
var pre *TreeNode
var traversal func(cur *TreeNode)
traversal = func(cur *TreeNode) {
if cur == nil {
return
}
traversal(cur.Right)
if pre != nil {
cur.Val += pre.Val
}
pre = cur
traversal(cur.Left)
}
traversal(root)
return root
}
|