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
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
難度簡單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
難度簡單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]
.
難度簡單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<parent_val and q_val<parent_val:
return self.lowestCommonAncestor(root.left,p,q)
else:
return root
說明:
- 所有節點的值都是唯一的。
- p、q 爲不同節點且均存在於給定的二叉搜索樹中。
【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
難度簡單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
難度簡單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
難度簡單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)
難度簡單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))
難度簡單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<R:
dfs(node.right)
self.ans = 0
dfs(root)
return self.ans
【牛客網】二叉樹的下一個節點
題目:給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指針。
思路:分兩種情況考慮,如果節點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