玩轉演算法面試LeetCode演算法練習——二叉樹與遞迴
目錄
104. 二叉樹的最大深度
給定一個二叉樹,找出其最大深度。
二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。
說明: 葉子節點是指沒有子節點的節點。
示例:
給定二叉樹 [3,9,20,null,null,15,7]
,
3
/ \
9 20
/ \
15 7
返回它的最大深度 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 maxDepth(self, root): """ :type root: TreeNode :rtype: int """ if root == None: return 0 leftDepth = self.maxDepth(root.left) + 1 rightDepth = self.maxDepth(root.right) + 1 return max(leftDepth,rightDepth)
111. 二叉樹的最小深度
給定一個二叉樹,找出其最小深度。
最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。
說明: 葉子節點是指沒有子節點的節點。
示例:
給定二叉樹 [3,9,20,null,null,15,7]
,
3
/ \
9 20
/ \
15 7
返回它的最小深度 2.
思路:
如果根節點為空,那麼返回0,如果左子樹為空,返回右子樹的最低高度+1,右子樹為空,返回左子樹最低高度+1,否則返回min(左子樹最低高度,右子樹最低高度)+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 minDepth(self, root): """ :type root: TreeNode :rtype: int """ if not root: return 0 if not root.right: return self.minDepth(root.left)+1 elif not root.left: return self.minDepth(root.right)+1 else: return min( self.minDepth( root.left ), self.minDepth( root.right ) ) + 1
226. 翻轉二叉樹
翻轉一棵二叉樹。
示例:
輸入:
4
/ \
2 7
/ \ / \
1 3 6 9
輸出:
4
/ \
7 2
/ \ / \
9 6 3 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 invertTree(self, root): """ :type root: TreeNode :rtype: TreeNode """ if root == None: return None self.invertTree(root.left) self.invertTree(root.right) root.left, root.right = root.right, root.left return root
100. 相同的樹
給定兩個二叉樹,編寫一個函式來檢驗它們是否相同。
如果兩個樹在結構上相同,並且節點具有相同的值,則認為它們是相同的。
示例 1:
輸入: 1 1
/ \ / \
2 3 2 3
[1,2,3], [1,2,3]
輸出: true
示例 2:
輸入: 1 1
/ \
2 2
[1,2], [1,null,2]
輸出: false
示例 3:
輸入: 1 1
/ \ / \
2 1 1 2
[1,2,1], [1,1,2]
輸出: 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 isSameTree(self, p, q):
"""
:type p: TreeNode
:type q: TreeNode
:rtype: bool
"""
if not p and not q:#遞迴邊界
return True
if p and q and p.val == q.val:
return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
else:
return False
101. 對稱二叉樹
給定一個二叉樹,檢查它是否是映象對稱的。
例如,二叉樹 [1,2,2,3,4,4,3]
是對稱的。
1
/ \
2 2
/ \ / \
3 4 4 3
但是下面這個 [1,2,2,null,3,null,3]
則不是映象對稱的:
1
/ \
2 2
\ \
3 3
思路主要參考leetcode100題,這裡將根節點的左右節點假設成兩顆獨立的樹,這樣解題跟100就是類似的了,區別:遞迴呼叫時,因是對稱,所以是左樹左節點與右樹右節點,左樹右節點與右樹左節點
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
def isSameTree(p,q):
if not p and not q:
return True
if p and q and p.val == q.val:
#因是對稱,所以是左樹左節點與右樹右節點,左樹右節點與右樹左節點
return isSameTree(p.left,q.right) and isSameTree(p.right,q.left)
else:
return False
if not root:
return True
else:
return isSameTree(root.left,root.right)
222. 完全二叉樹的節點個數
給出一個完全二叉樹,求出該樹的節點個數。
說明:
完全二叉樹的定義如下:在完全二叉樹中,除了最底層節點可能沒填滿外,其餘每層節點數都達到最大值,並且最下面一層的節點都集中在該層最左邊的若干位置。若最底層為第 h 層,則該層包含 1~ 2h 個節點。
示例:
輸入:
1
/ \
2 3
/ \ /
4 5 6
輸出: 6
思想是
計算樹的高度,判斷是否為滿二叉樹,YES則 節點個數=2^(height)-1。NO,遞迴判斷左右子樹是否為滿二叉樹,利用公式把節點計算出來。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
hl = hr = 0
l = r = root
while l:
hl += 1
l = l.left
while r:
hr += 1
r = r.right
if hl == hr:#相等為滿二叉樹
return 2 ** hl - 1
else:
return 1 + self.countNodes(root.left) + self.countNodes(root.right)
110. 平衡二叉樹
給定一個二叉樹,判斷它是否是高度平衡的二叉樹。
本題中,一棵高度平衡二叉樹定義為:
一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過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
。
思路:獲取當前節點的左右子數深度,絕對值差大於1,return False,小於1則依次遞迴左右子節點的左右子樹(每個左右子樹都可以想成獨立的二叉樹),只有左右子樹都為True,才為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):
"""
:type root: TreeNode
:rtype: bool
"""
if not root:
return True
lDepth = self.getDepth(root.left)
rDepth = self.getDepth(root.right)
if abs(lDepth-rDepth) > 1:
return False
else:
return self.isBalanced(root.left) and self.isBalanced(root.right)
def getDepth(self , root):
if root == None:
return 0;
lDepth = self.getDepth(root.left);
rDepth = self.getDepth(root.right);
return max(lDepth , rDepth) + 1;
112. 路徑總和
給定一個二叉樹和一個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等於目標和。
說明: 葉子節點是指沒有子節點的節點。
示例:
給定如下二叉樹,以及目標和 sum = 22
,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
返回 true
, 因為存在目標和為 22 的根節點到葉子節點的路徑 5->4->11->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 hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if root is None:
return False
if root.left is None and root.right is None:
return sum == root.val
return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right,sum-root.val)
404. 左葉子之和
計算給定二叉樹的所有左葉子之和。
示例:
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):
"""
:type root: TreeNode
:rtype: int
"""
sum = 0
if root == None:
return 0
if root.left and root.left.left ==None and root.left.right == None:
sum =root.left.val
return sum + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
257. 二叉樹的所有路徑
給定一個二叉樹,返回所有從根節點到葉子節點的路徑。
說明: 葉子節點是指沒有子節點的節點。
示例:
輸入:
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):
"""
:type root: TreeNode
:rtype: List[str]
"""
if root == None:
return []
res = []
if root.left == None and root.right == None:
res.append(str(root.val))
return res
leftS = self.binaryTreePaths(root.left)
for i in range(len(leftS)):
res.append(str(root.val)+'->'+leftS[i])
rightS = self.binaryTreePaths(root.right)
for i in range(len(rightS)):
res.append(str(root.val)+'->'+rightS[i])
return res
非遞迴:
# 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):
"""
:type root: TreeNode
:rtype: List[str]
"""
if not root:
return []
res, stack = [], [(root, "")]
while stack:
node, ls = stack.pop()
if not node.left and not node.right:
res.append(ls + str(node.val))
if node.left:
stack.append((node.left, ls + str(node.val) + "->"))
if node.right:
stack.append((node.right, ls + str(node.val) + "->"))
return res
113. 路徑總和 II
給定一個二叉樹和一個目標和,找到所有從根節點到葉子節點路徑總和等於給定目標和的路徑。
說明: 葉子節點是指沒有子節點的節點。
示例:
給定如下二叉樹,以及目標和 sum = 22
,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
返回:
[
[5,4,11,2],
[5,8,4,5]
]
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def dfs(self, node, target, sum, path):
if node is None:
return []
sum = sum + node.val
path = path + [node.val]
if node.left is None and node.right is None:
if sum == target:
self.target_paths.append(path)
return []
self.dfs(node.left, target, sum, path)
self.dfs(node.right, target, sum, path)
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: List[List[int]]
"""
self.target_paths = []
self.dfs(root, sum, 0, [])
return self.target_paths
129. 求根到葉子節點數字之和
給定一個二叉樹,它的每個結點都存放一個 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.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def sumNumbers(self, root):
"""
:type root: TreeNode
:rtype: int
"""
self.total = 0
self.dfs(root,0)
return self.total
def dfs(self, node, val):
if node is None:
return []
if node.left is None and node.right is None:
self.total = self.total + val * 10 + node.val
self.dfs(node.left, val * 10 + node.val)
self.dfs(node.right, val * 10 + node.val)
437. 路徑總和 III
給定一個二叉樹,它的每個結點都存放著一個整數值。
找出路徑和等於給定數值的路徑總數。
路徑不需要從根節點開始,也不需要在葉子節點結束,但是路徑方向必須是向下的(只能從父節點到子節點)。
二叉樹不超過1000個節點,且節點數值範圍是 [-1000000,1000000] 的整數。
示例:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 10 / \ 5 -3 / \ \ 3 2 11 / \ \ 3 -2 1 返回 3。和等於 8 的路徑有: 1. 5 -> 3 2. 5 -> 2 -> 1 3. -3 -> 11
# 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):
#在以root為根節點的二叉樹中,尋找和為sum的路徑,返回這樣的路徑個數
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: int
"""
if root == None:
return 0
res = self.findPath(root,sum)#包含當前根節點的路徑值
res += self.pathSum(root.left, sum)#不包含當前根節點左右子樹的路徑值
res += self.pathSum(root.right,sum)
return res
#在以node為根節點的二叉樹中,尋找包含node的路徑,和為sum
#返回這樣的路徑個數
def findPath(self,node,num):
if node == None:
return 0
res = 0
if node.val == num :
res += 1
res += self.findPath(node.left,num - node.val)
res += self.findPath(node.right,num - node.val)
return res