1 二叉树的前序遍历
def preorderTraversal(root: TreeNode):
if root is None:
return
list1 = []
list1.append(root.val)
if root.left:
list1 += preorderTraversal(root.left)
if root.right:
list1 += preorderTraversal(root.right)
return list1
2 二叉树的中序遍历
def inorderTraversal(root: TreeNode):
list = []
if root is None: #基线条件
return
if inorderTraversal(root.left):
list += inorderTraversal(root.left)
list += [root.val]
if inorderTraversal(root.right):
list += inorderTraversal(root.right)
return list
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
# check if root is None
check_list = [root]
output = []
while len(check_list) > 0:
stuff = check_list.pop()
if stuff is None:
continue
elif isinstance(stuff, TreeNode):
check_list.append(stuff.right)
check_list.append(stuff.val)
check_list.append(stuff.left)
else:
output.append(stuff)
return output
3 二叉树的后序遍历
def postorderTraversal(root: TreeNode):
list1 = []
if root is None:
return
if root.left:
list1 += postorderTraversal(root.left)
if root.right:
list1 += postorderTraversal(root.right)
list1 += [root.val]
return list1
4 二叉树的层次遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
levels = [] #存放二叉树层次遍历的结果
if root is None:
return levels
def help(root, level):
if len(levels) == level: #基线条件
levels.append([])
levels[level].append(root.val)
if root.left: #循环条件
help(root.left, level + 1)
if root.right:
help(root.right, level + 1)
help(root, 0)
return levels
面试题 04.04. 检查平衡性
难度简单23
实现一个函数,检查二叉树是否平衡。在这个问题中,平衡树的定义如下:任意一个节点,其两棵子树的高度差不超过 1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false 。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
if not root:
return True
return abs(self.depth(root.left)-self.depth(root.right))<2 and self.isBalanced(root.left) and self.isBalanced(root.right)
def depth(self,root):
if not root:
return 0
return max(self.depth(root.left),self.depth(root.right))+1
590. N叉树的后序遍历
难度简单82
给定一个 N 叉树,返回其节点值的后序遍历。
例如,给定一个 3叉树
:
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def postorder(self, root: 'Node') -> List[int]:
if root is None:
return []
stack,output = [root],[]
while stack:
root = stack.pop()
if root is not None:
output.append(root.val)
for c in root.children:
stack.append(c)
return output[::-1]
class Solution:
def postorder(self, root: 'Node') -> List[int]:
if root is None:
return []
res = []
for child in root.children:
res.extend(self.postorder(child))
res.append(root.val)
return res
返回其后序遍历: [5,6,3,2,4,1]
.
面试题68 - I. 二叉搜索树的最近公共祖先
难度简单36
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点2
和节点8
的最近公共祖先是6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点2
和节点4
的最近公共祖先是2
, 因为根据定义最近公共祖先节点可以为节点本身。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
#当前节点后者父节点
parent_val = root.val
# p节点的值
p_val = p.val
# q节点的值
q_val = q.val
if p_val>parent_val and q_val>parent_val:
return self.lowestCommonAncestor(root.right,p,q)
if p_val
说明:
【leetcode100】相同的树
class Solution:
def isSameTree(self, p: TreeNode, q: TreeNode) -> 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)
【leetcode101】相同的树给定一个二叉树,检查它是否是镜像对称的。
class Solution(object):
def isSymmetric(self, root):
def isSame(p, q): #定义递归判断子树是否相等
if not p and not q:
return True
if not p or not q:
return False
if p.val != q.val:
return False
return isSame(p.left, q.right) and isSame(p.right, q.left)
if root is None:
return True
return isSame(root, root)
【leetcode105】二叉树的最大深度
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if root is None:
return 0
left_depth= self.maxDepth(root.left)
right_depth = self.maxDepth(root.right)
return max(left_depth,right_depth)+1
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:
return 0
if not root.left:
return self.maxDepth(root.right)+1
if not root.right:
return self.maxDepth(root.left)+1
return max(self.maxDepth(root.left),self.maxDepth(root.right))+1
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxDepth(self, root: TreeNode) -> int:
stack =[]
if root is not None:
stack.append((1,root))
depth = 0
while stack != []:
current_depth,root = stack.pop()
if root is not None:
depth = max(depth,current_depth)
stack.append((current_depth+1,root.left))
stack.append((current_depth+1,root.right))
return depth
【leetcode111】 二叉树的最小深度
难度简单288
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7]
,
3
/ \
9 20
/ \
15 7
返回它的最小深度 2.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root : return 0
if not root.left :
return self.minDepth(root.right)+1
if not root.right :
return self.minDepth(root.left)+1
return min(self.minDepth(root.left),self.minDepth(root.right))+1
【leetcode106】根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
思路:
构建二叉树的问题本质上就是:
1 找到各个子树的根节点 root
2 构建该根节点的左子树
3 构建该根节点的右子树
class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if len(inorder) == 0:
return None
# 前序遍历第一个值为根节点
root = TreeNode(preorder[0])
# 因为没有重复元素,所以可以直接根据值来查找根节点在中序遍历中的位置
mid = inorder.index(preorder[0])
# 构建左子树
root.left = self.buildTree(preorder[1:mid+1], inorder[:mid])
# 构建右子树
root.right = self.buildTree(preorder[mid+1:], inorder[mid+1:])
return root
【leetcode106】从中序与后序遍历序列构造二叉树
根据一棵树的中序遍历与后序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
思路同105
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
if len(inorder) == 0:
return None
root = TreeNode(postorder[-1])
mid = inorder.index(postorder[-1])
root.left = self.buildTree(inorder[:mid], postorder[:mid])
root.right = self.buildTree(inorder[mid+1:], postorder[mid:len(postorder)-1])
return root
【leetcode108】将有序数组转换为二叉搜索树
题目:
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
思路:取序列中间元素为顶点,然后左边的是左子树,右边是右子树
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
if len(nums) == 0:
return None
root_index = len(nums) // 2
root = TreeNode(nums[root_index])
root.left = self.sortedArrayToBST(nums[:root_index])
root.right = self.sortedArrayToBST(nums[root_index+1:])
return root
【leetcode110】平衡二叉树
题目:
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false 。
思路:定义help函数,当左右子树高度差大于1时,返回False。但是不能放在help函数里 if abs(left_d, right_d):return True,因为help函数返回的实际上是树的深度,一个函数不能有两个类型不一样的返回值,因此我们借助类变量是全局变量,self.res,从而得出正确结果。
#复杂度比较高
# class Solution:
# def isBalanced(self, root: TreeNode) -> bool:
# def helper(node, level):
# if node is None:
# return level
# return max((helper(node.left, level+1), helper(node.right, level+1)))
# if root is None:
# return True
# if abs(helper(root.left, 0) - helper(root.right, 0)) > 1:
# return False
# return self.isBalanced(root.left) and self.isBalanced(root.right)
# class Solution:
# def isBalanced(self, root: TreeNode) -> bool:
# self.res = True
# def helper(node):
# if node is None:
# return 0
# left_tree = helper(node.left) + 1
# right_tree = helper(node.right) + 1
# if abs(left_tree - right_tree) > 1:
# self.res = False
# return max(left_tree, right_tree)
# helper(root)
# return self.res
# class Solution:
# def isBalanced(self, root: TreeNode) -> bool:
# self.res = True
# def helper(root):
# if not root:
# return 0
# left = helper(root.left) + 1
# right = helper(root.right) + 1
# #print(right, left)
# if abs(right - left) > 1:
# self.res = False
# return max(left, right)
# helper(root)
# return self.res
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
self.res = True
def helper(node, level):
if node is None:
return level
left_tree = helper(node.left, level+1)
right_tree = helper(node.right, level+1)
if abs(left_tree - right_tree) > 1:
self.res = False
return max(left_tree, right_tree)
helper(root, 0)
return self.res
#最后这个方法是我一开始的想法,一开始思路都正确,就是把if abs(left_tree - right_tree) > 1:return False改为self.res=True,一个函数要返回同一个类型才行
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
if not root:
return True
return abs(self.depth(root.left)-self.depth(root.right))<=1 and self.isBalanced(root.left) and self.isBalanced(root.right)
def depth(self,root):
if not root:
return 0
return max(self.depth(root.left),self.depth(root.right))+1
【leetcode111】二叉树的最小深度
题目:
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最小深度 2.
思路:
一开始写出的代码都不符合 1,2 这个测试用例,是因为没搞清楚题意
题目中说明:叶子节点是指没有子节点的节点,这句话的意思是 1 不是叶子节点, 2才是叶子节点,也就是说当root1没有右节点时,右节点为None,它的depth和左节点的depth是不能放在一起求最小值的。
题目问的是到叶子节点的最短距离,所以所有返回结果为 1 当然不是这个结果
另外这道题的关键是搞清楚递归结束条件
叶子节点的定义是左孩子和右孩子都为 null 时叫做叶子节点
当 root 节点左右孩子都为空时,返回 1
当 root 节点左右孩子有一个为空时,返回不为空的孩子节点的深度
当 root 节点左右孩子都不为空时,返回左右孩子较小深度的节点值
# class Solution:
# def minDepth(self, root: TreeNode) -> int:
# def help(node):
# if node is None:
# return 0
# if not node.left:
# return help(node.right) + 1
# if not node.right:
# return help(node.left) + 1
# return min(help(node.left), help(node.right)) + 1
# return help(root)
class Solution:
def minDepth(self, root: TreeNode) -> int:
def help(node, level):
if node is None:
return level
if not node.left:
return help(node.right, level+1)
if not node.right:
return help(node.left, level+1)
return min(help(node.left, level+1), help(node.right, level+1))
return help(root, 0)
【leetcode112】路径总和
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
思路:基线条件:返回true or false,因此当左右节点不存在且sum==0时,返回true。递归条件:是左右子树,左右子树只要有一个存在就可以返回true,因此递归的时候返回 左子树 or 右子树。【遇到返回中断类型的题,常规都是return 左 右】
如下代码是递归和非递归两种解法:
#第二次练习,出错在递归函数的return,注意有中断条件的时候,递归都是return(左子树右子树)
# class Solution:
# def hasPathSum(self, root: TreeNode, sum1) -> bool:
# if root is None:
# return False
# sum1 -= root.val
# if not root.left and not root.right and sum1 == 0:
# return True
# return self.hasPathSum(root.left, sum1) or self.hasPathSum(root.right, sum1)
class Solution:
def hasPathSum(self, root: TreeNode, sum1) -> bool:
if root is None:
return False
stack = [(root, sum1)]
while stack:
node, s = stack.pop()
s -= node.val
if not node.left and not node.right and s == 0:
return True
if node.left:
stack.append((node.left, s))
if node.right:
stack.append((node.right, s))
return False
【leetcode113】路径总和II
题目:
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
返回:
[
[5,4,11,2],
[5,8,4,5]
]
思路:与112题类似,但不同的是,需要返回所有的满足要求的列表,因此需要改动当到叶子节点判断的时候,如果符合要求就加入列表。
注意:1.区分深复制和浅复制:浅复制相当于引用,原来的变量变化还会导致浅复制后的变化;深复制不是引用。
2.左右子树递归时,递归函数的返回值类型要相同
3.如果函数1嵌套函数2,那函数1里的变量,对于函数2来说相当于全局变量。
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
def helper(node, sum, l:list):
if node is None:
return False
sum -= node.val
l.append(node.val)
if not node.left and not node.right and sum == 0:
res.append(l)
return True
helper(node.left, sum, copy.deepcopy(l))
helper(node.right, sum, copy.deepcopy(l))
return False
res = []
helper(root, sum, [])
return res
【leetcode113】路径总和II
题目:
给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。
例如,从根到叶子节点路径 1->2->3 代表数字 123。
计算从根到叶子节点生成的所有数字之和。
说明: 叶子节点是指没有子节点的节点。
示例 1:
输入: [1,2,3]
1
/ \
2 3
输出: 25
解释:
从根到叶子节点路径 1->2 代表数字 12.
从根到叶子节点路径 1->3 代表数字 13.
因此,数字总和 = 12 + 13 = 25.
示例 2:
输入: [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.
思路:思路完全同113题,只不过返回的是数字。
#同112和113题路径求和问题,也可以用字符串,但是我现在我咋会,等做了字符串我再来!!!
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
def list_to_number(m:list):
l = len(m)
n = 0
for i in range(l):
x = m[i] * pow(10, l - 1 - i)
n += x
return n
def helper(node, l:list):
if node is None:
return []
# res = []
l.append(node.val)
if not node.left and not node.right:
l_num = list_to_number(l)
res.append(l_num)
helper(node.left, copy.deepcopy(l))
helper(node.right, copy.deepcopy(l))
return res
res = []
s = helper(root, [])
total = 0
for i in s:
total += i
return total
257. 二叉树的所有路径
难度简单287
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入:
1
/ \
2 3
\
5
输出: ["1->2->5", "1->3"]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
def condtruc_path (root,path):
if root:
path = path + str(root.val)
if not root.left and not root.right:
paths.append(path)
else:
path=path+'->'
condtruc_path(root.left,path)
condtruc_path(root.right,path)
paths=[]
condtruc_path(root,'')
return paths
404. 左叶子之和
难度简单163
计算给定二叉树的所有左叶子之和。
示例:
3
/ \
9 20
/ \
15 7
在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def sumOfLeftLeaves(self, root: TreeNode) -> int:
result = 0
if root is None:
return 0
if root.left:
if not root.left.left and not root.left.right:
result += root.left.val
else :
result += self.sumOfLeftLeaves(root.left)
if root.right:
result += self.sumOfLeftLeaves(root.right)
return result
700. 二叉搜索树中的搜索
难度简单68
给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
例如,
给定二叉搜索树:
4
/ \
2 7
/ \
1 3
和值: 2
你应该返回如下子树:
2
/ \
1 3
在上述示例中,如果要找的值是 5
,但因为没有节点值为 5
,我们应该返回 NULL
。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def searchBST(self, root: TreeNode, val: int) -> TreeNode:
if root is None or val == root.val:
return root
if val < root.val:
return self.searchBST(root.left,val)
else:
return self.searchBST(root.right,val)
783. 二叉搜索树节点最小距离
难度简单65
给定一个二叉搜索树的根节点 root
,返回树中任意两节点的差的最小值。
示例:
输入: root = [4,2,6,1,3,null,null]
输出: 1
解释:
注意,root是树节点对象(TreeNode object),而不是数组。
给定的树 [4,2,6,1,3,null,null] 可表示为下图:
4
/ \
2 6
/ \
1 3
最小的差值是 1, 它是节点1和节点2的差值, 也是节点3和节点2的差值。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def minDiffInBST(self, root: TreeNode) -> int:
vals =[]
def dfs(node):
if node :
vals.append(node.val)
dfs(node.left)
dfs(node.right)
dfs(root)
vals.sort()
return min(vals[i+1]-vals[i] for i in range(len(vals)-1))
938. 二叉搜索树的范围和
难度简单116
给定二叉搜索树的根结点 root
,返回 L
和 R
(含)之间的所有结点的值的和。
二叉搜索树保证具有唯一的值。
示例 1:
输入:root = [10,5,15,3,7,null,18], L = 7, R = 15
输出:32
示例 2:
输入:root = [10,5,15,3,7,13,18,1,null,6], L = 6, R = 10
输出:23
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def rangeSumBST(self, root: TreeNode, L: int, R: int) -> int:
def dfs(node):
if node:
if L <= node.val <=R:
self.ans +=node.val
if L < node.val:
dfs(node.left)
if node.val
【牛客网】二叉树的下一个节点
题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
思路:分两种情况考虑,如果节点a存在右子树b,b存在左子树c,那么找到c的最左节点即为下一个节点。二是如果a不存在右子树b,那就找节点a的父节点,直到找到一个父节点是位于左子树为止。
# -*- coding:utf-8 -*-
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None
class Solution:
def GetNext(self, pNode):
if pNode is None:
return None
if pNode.right:
node = pNode.right
while node.left:
node = node.left
return node
else:
while pNode.next:
node = pNode.next
if node.left is pNode:
return node
pNode = pNode.next
return None