Leetcode题解 - 树

本系列为Leetcode刷题笔记,刷题平台为Leetcode中文站, 刷题按Tag分类。本系列题解汇总如下 (持续更新…):

本文主要是相关题目题解总结。

[TOC]

94. 二叉树的中序遍历

题目描述

给定一个二叉树,返回它的中序 遍历。

示例:

1
2
3
4
5
6
7
8
输入: [1,null,2,3]
1
\
2
/
3

输出: [1,3,2]

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

解题思路

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
res = []
self.dfs(root, res)
return res

def dfs(self, root, res):
if not root:
return
self.dfs(root.left, res)
res.append(root.val)
self.dfs(root.right, res)
return res

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []

res = []
stack = []
self.allLeftIntoStack(root, stack)
while stack:
root = stack.pop()
res.append(root.val)
if root.right:
self.allLeftIntoStack(root.right, stack)
return res

def allLeftIntoStack(self, root, stack):
while root:
stack.append(root)
root = root.left

95. 不同的二叉搜索树 II

题目描述

给定一个整数 n,生成所有由 1 … n 为节点所组成的二叉搜索树。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
输入: 3
输出:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]

解释:
以上的输出对应以下 5 种不同结构的二叉搜索树:

1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3

解题思路

依次以1~n作为根节点,其左边的为左子树,右边的为右子树。

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def generateTrees(self, n):
"""
:type n: int
:rtype: List[TreeNode]
"""
if n <= 0:
return []
return self.dfs(1, n+1)

def dfs(self, left, right):
res = []
for rootval in range(left, right):
leftnodes = self.dfs(left, rootval) or [None]
rightnodes = self.dfs(rootval+1, right) or [None]
for leftnode in leftnodes:
for rightnode in rightnodes:
root = TreeNode(rootval)
root.left = leftnode
root.right = rightnode
res.append(root)
return res

96. 不同的二叉搜索树

题目描述

给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?

示例:

1
2
3
4
5
6
7
8
9
10
输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:

1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3

解题思路

动态规划

给定一个序列1,…,n,为了构造所有的二叉树,我们遍历以i为节点,则1,…,i-1为构成左子树,i+1,…,n构成右子树;然后通过递归来构建左右子树,由于根节点是唯一的,所以可以保证构建的二叉树都是唯一的。

设dp[n]为1,…,n组成二叉搜索树的个数,初始化dp[0]=1,dp[1]=1,dp[2]=2;

dp[n] = F(1,n)+F(2,n)+…+F(n,n)
F(i,n) = dp(i-1)dp(n-i-1), 如F(1,3) = dp[0]dp[2]
F(i,n)为以i为根节点的二叉树个数。等于左右子树的排列的乘积。

dp[3] = dp[0]dp[2] + dp[1]dp[1] + dp[2]*dp[0]

因为dp[n] = dp[0]*dp[n-1] + dp[1][n-2] + … + dp[n-1]dp[0]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution(object):
def numTrees(self, n):
"""
:type n: int
:rtype: int
"""
dp = [1,1,2]
if n < 3:
return dp[n]
dp += [0]*(n-2)

for i in range(3, n+1):
for j in range(i):
dp[i] += dp[j]*dp[i-j-1]

return dp[-1]

98. 验证二叉搜索树

题目描述

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

1
2
3
4
5
输入:
2
/ \
1 3
输出: true

示例 2:

1
2
3
4
5
6
7
8
9
输入:
5
/ \
1 4
/ \
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。

解题思路

根据二叉搜索树的定义,左子树的值在(left, root.val)之间,右子树的值在(root.val, right),每次递归是判断当前节点值是否满足取值上界和下界,计算下一节点是要根据左右节点进行更新上下界。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
return self.dfs(root, float('-inf'), float('inf'))

def dfs(self, root, left, right):
if not root:
return True
if root.val <= left or root.val >= right:
return False
return self.dfs(root.left, left, root.val) and self.dfs(root.right, root.val, right)

先中序遍历(递归),判断数组是否升序。

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
queue = []
self.inorder(root, queue)
for i in range(1, len(queue)):
if queue[i] <= queue[i-1]:
return False
return True

def inorder(self, root, queue):
if not root:
return
self.inorder(root.left, queue)
queue.append(root.val)
self.inorder(root.right, queue)
return queue

先中序遍历(迭代),判断数组是否升序。

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
34
35
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
queue = []
stack = []
self.LeftintoStack(root, stack)
while stack:
root = stack.pop()
queue.append(root.val)
if root.right:
self.LeftintoStack(root.right, stack)

for i in range(1, len(queue)):
if queue[i] <= queue[i-1]:
return False
return True

def LeftintoStack(self, root, stack):
if not root:
return
while root:
stack.append(root)
root = root.left

100. 相同的树

题目描述

给定两个二叉树,编写一个函数来检验它们是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

1
2
3
4
5
6
7
输入:       1         1
/ \ / \
2 3 2 3

[1,2,3], [1,2,3]

输出: true

示例 2:

1
2
3
4
5
6
7
输入:      1          1
/ \
2 2

[1,2], [1,null,2]

输出: false

示例 3:

1
2
3
4
5
6
7
输入:       1         1
/ \ / \
2 1 1 2

[1,2,1], [1,1,2]

输出: false

解题思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def isSameTree(self, p, q):
"""
:type p: TreeNode
:type q: TreeNode
:rtype: bool
"""
if not p and not q:
return True
if not p or not q:
return False
if p.val != q.val:
return False
return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

101. 对称二叉树

题目描述

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

1
2
3
4
5
    1
/ \
2 2
/ \ / \
3 4 4 3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

1
2
3
4
5
  1
/ \
2 2
\ \
3 3

说明:

如果你可以运用递归和迭代两种方法解决这个问题,会很加分。

解题思路

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
return self.judge(root.left, root.right)

def judge(self, left, right):
if not left and not right:
return True
if not left or not right:
return False
if left.val != right.val:
return False
return self.judge(left.left, right.right) and self.judge(left.right, right.left)

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
queue = collections.deque()
queue.append([root.left, root.right])
while queue:
pair = queue.popleft()
left, right = pair[0], pair[1]
if not left and not right:
continue
if not left or not right:
return False
if left.val != right.val:
return False
queue.append([left.left, right.right])
queue.append([left.right, right.left])

return True

102. 二叉树的层次遍历

题目描述

给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。

例如:
给定二叉树: [3,9,20,null,null,15,7],

1
2
3
4
5
  3
/ \
9 20
/ \
15 7

返回其层次遍历结果:

1
2
3
4
5
[
[3],
[9,20],
[15,7]
]

解题思路

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []

queue = [root]
res = []

while queue:
temp = []
for i in range(len(queue)):
node = queue.pop(0)
temp.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if temp:
res.append(temp)

return res

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []

res = []
self.dfs(root, 0, res)
return res

def dfs(self, root, level, res):
if not root:
return
if len(res) == level:
res.append([])
res[level].append(root.val)
if root.left:
self.dfs(root.left, level+1, res)
if root.right:
self.dfs(root.right, level+1, res)

103. 二叉树的锯齿形层次遍历

题目描述

给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

例如:
给定二叉树 [3,9,20,null,null,15,7],

1
2
3
4
5
  3
/ \
9 20
/ \
15 7

返回锯齿形层次遍历如下:

1
2
3
4
5
[
[3],
[20,9],
[15,7]
]

解题思路

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def zigzagLevelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
res = []
queue = [root]
while queue:
temp = []
for i in range(len(queue)):
node = queue.pop(0)
temp.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if temp:
res.append(temp)

for i in range(1, len(res), 2):
res[i] = res[i][::-1]

return res

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def zigzagLevelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
res = []
self.dfs(root, 0, res)

for i in range(1, len(res), 2):
res[i] = res[i][::-1]

return res

def dfs(self, root, level, res):
if not root:
return
if len(res) == level:
res.append([])
res[level].append(root.val)
if root.left:
self.dfs(root.left, level+1, res)
if root.right:
self.dfs(root.right, level+1, res)

104. 二叉树的最大深度

题目描述

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7],

1
2
3
4
5
  3
/ \
9 20
/ \
15 7

返回它的最大深度 3 。

解题思路

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
res = 0
queue = [root]
while queue:
temp = []
for i in range(len(queue)):
node = queue.pop(0)
temp.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if temp:
res += 1
return res

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
res = 0
queue = [root]
while queue:
temp = []
for node in queue:
if node.left:
temp.append(node.left)
if node.right:
temp.append(node.right)
res += 1
queue = temp
return res

105. 从前序与中序遍历序列构造二叉树

题目描述

根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

1
2
3
4
5
  3
/ \
9 20
/ \
15 7

解题思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if not preorder or not inorder:
return None
rootval = preorder[0]
index = inorder.index(rootval)
root = TreeNode(rootval)
root.left = self.buildTree(preorder[1:index+1], inorder[:index])
root.right = self.buildTree(preorder[index+1:], inorder[index+1:])
return root

106. 从中序与后序遍历序列构造二叉树

题目描述

根据一棵树的中序遍历与后序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

1
2
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]

返回如下的二叉树:

1
2
3
4
5
  3
/ \
9 20
/ \
15 7

解题思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
"""
if not inorder or not postorder:
return None
rootval = postorder[-1]
index = inorder.index(rootval)
root = TreeNode(rootval)
root.left = self.buildTree(inorder[:index], postorder[:index])
root.right = self.buildTree(inorder[index+1:], postorder[index:-1])
return root

107. 二叉树的层次遍历 II

题目描述

给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如:
给定二叉树 [3,9,20,null,null,15,7],

1
2
3
4
5
  3
/ \
9 20
/ \
15 7

返回其自底向上的层次遍历为:

1
2
3
4
5
[
[15,7],
[9,20],
[3]
]

解题思路

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def levelOrderBottom(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
res = []
self.dfs(root, 0, res)
return res[::-1]

def dfs(self, root, level, res):
if not root:
return
if len(res) == level:
res.append([])
res[level].append(root.val)
if root.left:
self.dfs(root.left, level+1, res)
if root.right:
self.dfs(root.right, level+1, res)

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def levelOrderBottom(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
res = []
queue = [root]
while queue:
temp = []
for i in range(len(queue)):
node = queue.pop(0)
temp.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if temp:
res.append(temp)

return res[::-1]

108. 将有序数组转换为二叉搜索树

题目描述

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

1
2
3
4
5
6
7
8
9
给定有序数组: [-10,-3,0,5,9],

一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

0
/ \
-3 9
/ /
-10 5

解题思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def sortedArrayToBST(self, nums):
"""
:type nums: List[int]
:rtype: TreeNode
"""
if len(nums) == 0:
return None
mid = len(nums)//2
root = TreeNode(nums[mid])
root.left = self.sortedArrayToBST(nums[:mid])
root.right = self.sortedArrayToBST(nums[mid+1:])
return root

110. 平衡二叉树

题目描述

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

示例 1:

给定二叉树 [3,9,20,null,null,15,7]

1
2
3
4
5
  3
/ \
9 20
/ \
15 7

返回 true 。

示例 2:

给定二叉树 [1,2,2,3,3,null,null,4,4]

1
2
3
4
5
6
7
      1
/ \
2 2
/ \
3 3
/ \
4 4

返回 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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def isBalanced(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
leftdepth = self.getdepth(root.left)
rightdepth = self.getdepth(root.right)
if abs(leftdepth-rightdepth) > 1:
return False
return self.isBalanced(root.left) and self.isBalanced(root.right)

def getdepth(self, root):
if not root:
return 0
return max(self.getdepth(root.left), self.getdepth(root.right)) + 1

111. 二叉树的最小深度

题目描述

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

1
2
3
4
5
  3
/ \
9 20
/ \
15 7

返回它的最小深度 2.

解题思路

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def minDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
res = 0
queue = [root]
while queue:
res += 1
for i in range(len(queue)):
node = queue.pop(0)
if not node.left and not node.right:
return res
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)

return res

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def minDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
if not root.left and root.right:
return self.minDepth(root.right) + 1
if not root.right and root.left:
return self.minDepth(root.left) + 1
return min(self.minDepth(root.left), self.minDepth(root.right)) + 1

112. 路径总和

题目描述

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 sum = 22,

1
2
3
4
5
6
7
      5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1

返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

解题思路

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if not root:
return False
if not root.left and not root.right:
return root.val == sum
return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right, sum-root.val)

回溯

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if not root:
return False

return self.dfs(root, sum-root.val)

def dfs(self, root, target):
if not root:
return False
if target == 0 and not root.left and not root.right:
return True
left, right = False, False
if root.left:
left = self.dfs(root.left, target-root.left.val)
if root.right:
right = self.dfs(root.right, target-root.right.val)
return left or right

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if not root:
return False
queue = [(root, sum-root.val)]

while queue:
node, target = queue.pop(0)
if not node:
continue
if not node.left and not node.right and target == 0:
return True
if node.left:
queue.append((node.left, target-node.left.val))
if node.right:
queue.append((node.right, target-node.right.val))
return False

113. 路径总和 II

题目描述

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 sum = 22,

1
2
3
4
5
6
7
      5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1

返回:

1
2
3
4
[
[5,4,11,2],
[5,8,4,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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: List[List[int]]
"""
if not root:
return []
res = []
self.dfs(root, [root.val], res, sum)
return res

def dfs(self, root, path, res, target):
if not root:
return
if sum(path) == target and not root.left and not root.right:
res.append(path)
if root.left:
self.dfs(root.left, path+[root.left.val], res, target)
if root.right:
self.dfs(root.right, path+[root.right.val], res, target)

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: List[List[int]]
"""
if not root:
return []
res = []
self.dfs(root, [], res, sum)
return res

def dfs(self, root, path, res, target):
if not root:
return
if not root.left and not root.right and target == root.val:
path.append(root.val)
res.append(path)
if root.left:
self.dfs(root.left, path+[root.val], res, target-root.val)
if root.right:
self.dfs(root.right, path+[root.val], res, target-root.val)
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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: List[List[int]]
"""
if not root:
return []
#if not root.left and not root.right and root.val == sum:
# return [[root.val]]
#temp = self.pathSum(root.left, sum-root.val) + self.pathSum(root.right, sum-root.val)
#return [[root.val]+i for i in temp]

res = []
if not root.left and not root.right and root.val == sum:
return [[root.val]]
temp = self.pathSum(root.left, sum-root.val) + self.pathSum(root.right, sum-root.val)
for i in temp:
res.append([root.val]+i)
return res

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: List[List[int]]
"""

if not root:
return []
res = []
queue = [(root, root.val, [root.val])]
while queue:
node, target, temp = queue.pop(0)
if not node.left and not node.right and target == sum:
res.append(temp)
if node.left:
queue.append((node.left, target+node.left.val, temp+[node.left.val]))
if node.right:
queue.append((node.right, target+node.right.val, temp+[node.right.val]))
return res

114. 二叉树展开为链表

题目描述

给定一个二叉树,原地将它展开为链表。

例如,给定二叉树

1
2
3
4
5
    1
/ \
2 5
/ \ \
3 4 6

将其展开为:

1
2
3
4
5
6
7
8
9
10
11
1
\
2
\
3
\
4
\
5
\
6

解题思路

先前序遍历,在讲所有节点的左子树置空,并将右子树置为下一节点。空间复杂度为O(n)。

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
34
35
36
37
38
39
40
41
42
43
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def flatten(self, root):
"""
:type root: TreeNode
:rtype: void Do not return anything, modify root in-place instead.
"""
if not root:
return root

#迭代
res = []
stack = [root]
while stack:
node = stack.pop()
res.append(node)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)

for i in range(len(res)-1):
res[i].left = None
res[i].right = res[i+1]
# 递归
res = []
self.preorder(root, res)
for i in range(len(res)-1):
res[i].left = None
res[i].right = res[i+1]

def preorder(self, root, res):
if not root:
return
res.append(root)
self.preorder(root.left, res)
self.preorder(root.right, res)

116. 填充同一层的兄弟节点

题目描述

给定一个二叉树

1
2
3
4
5
struct TreeLinkNode {
TreeLinkNode *left;
TreeLinkNode *right;
TreeLinkNode *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

说明:

你只能使用额外常数空间。
使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。
你可以假设它是一个完美二叉树(即所有叶子节点都在同一层,每个父节点都有两个子节点)。
示例:

给定完美二叉树,

1
2
3
4
5
     1
/ \
2 3
/ \ / \
4 5 6 7

调用你的函数后,该完美二叉树变为:

1
2
3
4
5
     1 -> NULL
/ \
2 -> 3 -> NULL
/ \ / \
4->5->6->7 -> NULL

解题思路

递归,从根节点开始找到任意节点,将其左孩子指向其右孩子,如果该节点的next节点已经指向其他节点,说明需要连接两个子树;比如2->3,需要把2的左子树4指向5,同时需要将左右子树连接起来,即5->6。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Definition for binary tree with next pointer.
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None

class Solution:
# @param root, a tree link node
# @return nothing
def connect(self, root):
if not root:
return
if root.right:
root.left.next = root.right
if root.next:
root.right.next = root.next.left
self.connect(root.left)
self.connect(root.right)

迭代。层次遍历,将队列中的元素弹出时,如果他不是最后一个元素,则将其的next节点指向队列中的下一个节点。

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
# Definition for binary tree with next pointer.
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None

class Solution:
# @param root, a tree link node
# @return nothing
def connect(self, root):
if not root:
return

queue = [root]
while queue:
length = len(queue)
for i in range(length):
node = queue.pop(0)
if i < length - 1:
node.next = queue[0]
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)

117. 填充同一层的兄弟节点 II

题目描述

给定一个二叉树

1
2
3
4
5
struct TreeLinkNode {
TreeLinkNode *left;
TreeLinkNode *right;
TreeLinkNode *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

说明:

  • 你只能使用额外常数空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

示例:

给定二叉树,

1
2
3
4
5
     1
/ \
2 3
/ \ \
4 5 7

调用你的函数后,该二叉树变为:

1
2
3
4
5
     1 -> NULL
/ \
2 -> 3 -> NULL
/ \ \
4-> 5 -> 7 -> NULL

解题思路

递归。主要先右再左,因为在递归左子树的时候,需要不断寻找同层的next节点,需要保证右子树先建立好next节点。

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
34
35
36
37
38
39
40
41
42
# Definition for binary tree with next pointer.
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None

class Solution:
# @param root, a tree link node
# @return nothing
def connect(self, root):
if not root:
return

if root.left and root.right:
root.left.next = root.right
temp = root.next
while temp:
if temp.left:
root.right.next = temp.left; break
if temp.right:
root.right.next = temp.right; break
temp = temp.next
elif root.left:
temp = root.next
while temp:
if temp.left:
root.left.next = temp.left; break
if temp.right:
root.left.next = temp.right; break
temp = temp.next
elif root.right:
temp = root.next
while temp:
if temp.left:
root.right.next = temp.left; break
if temp.right:
root.right.next = temp.right; break
temp = temp.next
self.connect(root.right)
self.connect(root.left)

迭代。和上题思路代码一样

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
# Definition for binary tree with next pointer.
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None

class Solution:
# @param root, a tree link node
# @return nothing
def connect(self, root):
if not root:
return

queue = collections.deque()
queue.append(root)
while queue:
length = len(queue)
for i in range(length):
node = queue.popleft()
if i < length - 1:
node.next = queue[0]
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)

129. 求根到叶子节点数字之和

题目描述

给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。

例如,从根到叶子节点路径 1->2->3 代表数字 123。

计算从根到叶子节点生成的所有数字之和。

说明: 叶子节点是指没有子节点的节点。

示例 1:

1
2
3
4
5
6
7
8
9
输入: [1,2,3]
1
/ \
2 3
输出: 25
解释:
从根到叶子节点路径 1->2 代表数字 12.
从根到叶子节点路径 1->3 代表数字 13.
因此,数字总和 = 12 + 13 = 25.

示例 2:

1
2
3
4
5
6
7
8
9
10
11
12
输入: [4,9,0,5,1]
4
/ \
9 0
/ \
5 1
输出: 1026
解释:
从根到叶子节点路径 4->9->5 代表数字 495.
从根到叶子节点路径 4->9->1 代表数字 491.
从根到叶子节点路径 4->0 代表数字 40.
因此,数字总和 = 495 + 491 + 40 = 1026.

解题思路

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def sumNumbers(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0

self.res = 0
self.dfs(root, root.val)
return self.res

def dfs(self, root, path):

if not root.left and not root.right:
self.res += path
if root.left:
self.dfs(root.left, path*10+root.left.val)
if root.right:
self.dfs(root.right, path*10+root.right.val)

迭代。栈

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def sumNumbers(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0

res = 0
stack = [(root, root.val)]
while stack:
node, val = stack.pop()
if not node.left and not node.right:
res += val
if node.left:
stack.append((root.left, val*10+root.left.val))
if node.right:
stack.append((root.right, val*10+root.right.val))
return res

迭代。队列

144. 二叉树的前序遍历

题目描述

给定一个二叉树,返回它的 前序 遍历。

示例:

1
2
3
4
5
6
7
8
输入: [1,null,2,3]  
1
\
2
/
3

输出: [1,2,3]

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

解题思路

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
res = []
self.dfs(root, res)
return res

def dfs(self, root, res):
if not root:
return
res.append(root.val)
self.dfs(root.left, res)
self.dfs(root.right,res)

迭代。栈

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
res = []
stack = [root]
while stack:
node = stack.pop()
res.append(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return res

迭代。队列

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
res = []
queue = collections.deque()
queue.append(root)
while queue:
node = queue.pop()
res.append(node.val)
if node.right:
queue.append(node.right)
if node.left:
queue.append(node.left)
return res

145. 二叉树的后序遍历

题目描述

给定一个二叉树,返回它的 后序 遍历。

示例:

1
2
3
4
5
6
7
8
输入: [1,null,2,3]  
1
\
2
/
3

输出: [3,2,1]

解题思路

常规思路1 递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def postorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""

if not root:
return []

res = []
self.postOrder(root, res)
return res

def postOrder(self, root, res):
if not root:
return
self.postOrder(root.left, res)
self.postOrder(root.right, res)
res.append(root.val)

常规思路2 迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def postorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""

if not root:
return []

res = []
stack = [root]
stack.append(root)
while stack:
node = stack.pop()
if stack and node == stack[-1]:
if node.right:
stack.append(node.right)
stack.append(node.right)
if node.left:
stack.append(node.left)
stack.append(node.left)
else:
res.append(node.val)

return res

思路3 借鉴前序根左右遍历的思路,按照根右左的方式遍历,最后的结果翻转即为后序遍历结果。以下为递归和非递归的代码。

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

# 递归
class Solution(object):
def postorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""

if not root:
return []

res = []
self.help(root, res)
return res[::-1]

def help(self, root, res):
if not root:
return
res.append(root.val)
self.help(root.right, res)
self.help(root.left, res)

# 非递归
class Solution(object):
def postorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""

if not root:
return []

res = []
stack = [root]
while stack:
node = stack.pop()
res.append(node.val)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)

return res[::-1]

199. 二叉树的右视图

题目描述

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例:

1
2
3
4
5
6
7
8
9
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:

1 <---
/ \
2 3 <---
\ \
5 4 <---

解题思路

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def rightSideView(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []

res = []
self.level(root, 0, res)
return [res[i][-1] for i in range(len(res))]

def level(self, root, level, res):
if not root:
return
if len(res) == level:
res.append([])
res[level].append(root.val)
self.level(root.left, level+1, res)
self.level(root.right, level+1, res)

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def rightSideView(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
queue = [root]
res = []
while queue:
temp = []
for i in range(len(queue)):
cur = queue.pop(0)
temp.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
if temp:
res.append(temp[-1])
return res

208. 实现 Trie (前缀树)

题目描述

实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。

示例:

1
2
3
4
5
6
7
8
Trie trie = new Trie();

trie.insert("apple");
trie.search("apple"); // 返回 true
trie.search("app"); // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");
trie.search("app"); // 返回 true

说明:

  • 你可以假设所有的输入都是由小写字母 a-z 构成的。
  • 保证所有输入均为非空字符串。

解题思路

字典树
性质:

  • 根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
  • 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
  • 每个节点的所有子节点包含的字符互不相同。
  • 通常在实现的时候,会在节点结构中设置一个标志,用来标记该结点处是否构成一个单词(关键字)。

可以看出,Trie树的关键字一般都是字符串,而且Trie树把每个关键字保存在一条路径上,而不是一个结点中。另外,两个有公共前缀的关键字,在Trie树中前缀部分的路径相同,所以Trie树又叫做前缀树(Prefix Tree)。

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

import collections
class Node(object):
def __init__(self):
self.children = collections.defaultdict(Node)
self.isWord = False

class Trie(object):

def __init__(self):
"""
Initialize your data structure here.
"""
self.root = Node()

def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: None
"""
cur = self.root
for w in word:
cur = cur.children[w]
cur.isWord = True

def search(self, word):
"""
Returns if the word is in the trie.
:type word: str
:rtype: bool
"""
cur = self.root
for w in word:
cur = cur.children.get(w)
if not cur:
return False
return cur.isWord

def startsWith(self, prefix):
"""
Returns if there is any word in the trie that starts with the given prefix.
:type prefix: str
:rtype: bool
"""
cur = self.root
for w in prefix:
cur = cur.children.get(w)
if not cur:
return False
return True



# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

222. 完全二叉树的节点个数

题目描述

给出一个完全二叉树,求出该树的节点个数。

说明:

完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例:

1
2
3
4
5
6
7
8
输入: 
1
/ \
2 3
/ \ /
4 5 6

输出: 6

解题思路

分治递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
return 1 + self.countNodes(root.left) + self.countNodes(root.right)

对于一棵满二叉树,若其高度为l,则节点个数为2^l-1个节点。
递归求解。

  1. 首先从根节点开始,沿左子树的左节点一路向下,得到整棵二叉树的最大深度h_l(因为是完全二叉树,所以最左侧叶节点的高度可以代表整棵树的最大高度)。
  2. 其次计算根节点右子树最左侧子节点的高度h_r。
    若h_l = h_r,则说明左子树为一满二叉树,可通过公式2^h_l计算其节点个数。
    若h_l > h_r(h_l = h_r + 1),则说明右子树为满二叉树,可通过公式2^h_r计算其节点个数。
  3. 递归计算另一棵子树的节点数目。
    终止条件:
    当前节点高度为子树高度h_l,h_r均为0,说明其左右节点均为空,没有进入循环调节,即到达最后的叶节点。
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
34
35
36
37
38
39
40
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0

h_l, h_r = 0, 0
curRoot = root.left
while curRoot:
h_l += 1
curRoot = curRoot.left

curRoot = root.right
if curRoot:
h_r += 1
curRoot = curRoot.left
while curRoot:
h_r += 1
curRoot = curRoot.left

if h_l == h_r:
sum_l = 2**h_l - 1
sum_r = self.countNodes(root.right)

if h_l > h_r:
sum_r = 2**h_r - 1
sum_l = self.countNodes(root.left)


return sum_l + sum_r + 1

226. 翻转二叉树

题目描述

翻转一棵二叉树。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
输入:

4
/ \
2 7
/ \ / \
1 3 6 9
输出:

4
/ \
7 2
/ \ / \
9 6 3 1

解题思路

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def invertTree(self, root):
"""
:type root: TreeNode
:rtype: TreeNode
"""

if not root:
return root

temp = root.left
root.left = root.right
root.right = temp

self.invertTree(root.left)
self.invertTree(root.right)

return root

230. 二叉搜索树中第K小的元素

题目描述

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。

说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。

示例 1:

1
2
3
4
5
6
7
输入: root = [3,1,4,null,2], k = 1
3
/ \
1 4
\
2
输出: 1

示例 2:

1
2
3
4
5
6
7
8
9
输入: root = [5,3,6,2,4,null,null,1], k = 3
5
/ \
3 6
/ \
2 4
/
1
输出: 3

解题思路

中序遍历。

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def kthSmallest(self, root, k):
"""
:type root: TreeNode
:type k: int
:rtype: int
"""

if not root or k <= 0:
return 0
res = []
self.inorder(root, res)
return res[k-1]


def inorder(self, root, res):
if not root:
return
self.inorder(root.left, res)
res.append(root.val)
self.inorder(root.right, res)

python3的yield。

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
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution:
def kthSmallest(self, root: TreeNode, k: int) -> int:

if not root or k <= 0:
return 0

iteration = self.inorder(root)

res = 0
for i in range(k):
res = next(iteration)
return res


def inorder(self, root):
if root:
yield from self.inorder(root.left)
yield root.val
yield from self.inorder(root.right)

235. 二叉搜索树的最近公共祖先

题目描述

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

1
2
3
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。

示例 2:

1
2
3
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

  1. 所有节点的值都是唯一的。
  2. p、q 为不同节点且均存在于给定的二叉搜索树中。

解题思路

首先保证p的值一定比q的小
利用二叉搜索树的特性,左子树一定比根节点小,右子树一定比根节点大;

  • p和q在root两侧,那么root就是公共祖先
  • pq均小于root,那么从左子树寻找
  • pq均大于root,那么从右子树寻找
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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""

if p.val > q.val:
p, q = q, p

node = root
while True:
if node.val == p.val or node.val == q.val:
return node
elif p.val < node.val < q.val:
return node
elif q.val < node.val:
node = node.left
else:
node = node.right

可以将其看做普通的二叉树,使用236题的代码也可AC.

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""

if not root or root == p or root == q:
return root

left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)

if left and right:
return root
elif not left and not right:
return None
return left if left else right

236. 二叉树的最近公共祖先

题目描述

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

示例 1:

1
2
3
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。

示例 2:

1
2
3
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

说明:

所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。

解题思路

递归。对以root为根的树进行查找p和q

如果root为空或root==p或root==q,直接返回root,表明当前树已经查询完成;

如果当前结点不等于p或q,p和q要么分别位于左右子树中,要么同时位于左子树,或者同时位于右子树,那么我们分别来讨论:

否则对左右子树进行查找,根据左右子树的返回值进行判断:

  1. 左右子树的返回值都不为null, 由于值唯一左右子树的返回值就是p和q, 此时root为LCA
  2. 如果左右子树返回值只有一个不为null, 说明只有p和q存在与左或右子树中, 最先找到的那个节点为LCA
  3. 左右子树返回值均为null, p和q均不在树中, 返回null
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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""

if not root or root == p or root == q:
return root

left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)

if not left and not right:
return None
elif left and right:
return root
else:
return left if left else right

257. 二叉树的所有路径

题目描述

给定一个二叉树,返回所有从根节点到叶子节点的路径。

说明: 叶子节点是指没有子节点的节点。

示例:

1
2
3
4
5
6
7
8
9
10
11
输入:

1
/ \
2 3
\
5

输出: ["1->2->5", "1->3"]

解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3

解题思路

递归

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def binaryTreePaths(self, root):
"""
:type root: TreeNode
:rtype: List[str]
"""

if not root:
return []

res = []
self.dfs(root, str(root.val), res)

return res

def dfs(self, root, path, res):
if not root:
return
if not root.left and not root.right:
res.append(path)
return
if root.left:
self.dfs(root.left, path + '->' + str(root.left.val), res)
if root.right:
self.dfs(root.right, path + '->' + str(root.right.val), res)

迭代

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def binaryTreePaths(self, root):
"""
:type root: TreeNode
:rtype: List[str]
"""

if not root:
return []

res = []
stack = [(root, str(root.val))]

while stack:
node, path = stack.pop(0)
if not node.left and not node.right:
res.append(path)
if node.left:
stack.append((node.left, path + '->' + str(node.left.val)))
if node.right:
stack.append((node.right, path + '->' + str(node.right.val)))

return res

297. 二叉树的序列化与反序列化

题目描述

序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。

请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。

示例:

1
2
3
4
5
6
7
8
9
你可以将以下二叉树:

1
/ \
2 3
/ \
4 5

序列化为 "[1,2,3,null,null,4,5]"

提示: 这与 Leetcode 目前使用的方式一致,详情请参阅 Leetcode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。

说明: 不要使用类的成员 / 全局 / 静态变量来存储状态,你的序列化和反序列化算法应该是无状态的。

解题思路

采用前序遍历

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Codec:

def serialize(self, root):
"""Encodes a tree to a single string.

:type root: TreeNode
:rtype: str
"""

if not root:
return '#'
return str(root.val) + ',' + self.serialize(root.left) + ',' + self.serialize(root.right)

def deserialize(self, data):
"""Decodes your encoded data to tree.

:type data: str
:rtype: TreeNode
"""
tree = data.split(',')
return self.Tree(tree)

def Tree(self, tree):
if not tree:
return None

root = None
val = tree.pop(0)
if val != '#':
root = TreeNode(int(val))
root.left = self.Tree(tree)
root.right = self.Tree(tree)

return root



# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))

337. 打家劫舍 III

题目描述

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。

示例 1:

1
2
3
4
5
6
7
8
9
10
输入: [3,2,3,null,3,null,1]

3
/ \
2 3
\ \
3 1

输出: 7
解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.

示例 2:

1
2
3
4
5
6
7
8
9
10
输入: [3,4,5,1,3,null,1]

3
/ \
4 5
/ \ \
1 3 1

输出: 9
解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.

解题思路

对于一个以root为根节点的二叉树而言:

  • 如果偷root节点,那么不能偷其左右子节点
  • 如果不偷该节点,那么可以偷其左右子节点
  • 比较两种方式的大小,取大值

递归完成,每次返回的是(偷,不偷)当前节点的值,如果偷根节点了,那么不能偷其子节点,即加上的是left[1],和right[1],1表示的是返回不偷该节点的值。

如果不偷根节点,那么可以偷左右子节点

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
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""

if not root:
return 0

return max(self.tryrob(root))

def tryrob(self, root):
if not root:
return (0, 0)

left = self.tryrob(root.left)
right = self.tryrob(root.right)

# rob now
now = root.val + left[1] + right[1]

# rob later
later = max(left) + max(right)

return (now, later)

404. 左叶子之和

题目描述

计算给定二叉树的所有左叶子之和。

示例:

1
2
3
4
5
6
7
    3
/ \
9 20
/ \
15 7

在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回24

解题思路

递归,当遇到左叶子节点时加到和里,然后取递归右子树

否则,还没遇到左叶子节点,遍历左子树和右子树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None

class Solution(object):
def sumOfLeftLeaves(self, root):
"""
:type root: TreeNode
:rtype: int
"""

if not root:
return 0

if root.left and not root.left.left and not root.left.right:
return root.left.val + self.sumOfLeftLeaves(root.right)
else:
return self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)

Donate comment here
------------The End------------
0%