劍指offer-二叉樹

1. 平衡二叉樹node

輸入一棵二叉樹,判斷該二叉樹是不是平衡二叉樹。數組

解:app

要麼是一顆空樹,要麼左右子樹都是平衡二叉樹且左右子樹深度之差不超過1ide

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     def IsBalanced_Solution(self, pRoot):
 8         # write code here
 9         if not pRoot:
10             return True
11         res = abs(self.getDepth(pRoot.left) - self.getDepth(pRoot.right))
12         if res <= 1 and self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right):
13             return True
14         return False
15         
16     def getDepth(self, root):
17         if not root:
18             return 0
19         if not (root.left or root.right):
20             return 1
21         return max(self.getDepth(root.left), self.getDepth(root.right)) + 1
View Code

  

 

2. 二叉樹的深度函數

輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次通過的結點(含根、葉結點)造成樹的一條路徑,最長路徑的長度爲樹的深度。spa

解:3d

層次遍歷,bfs 實現指針

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     def TreeDepth(self, pRoot):
 8         # write code here
 9         if not pRoot:
10             return 0
11         depth = 0
12         queue = [pRoot]
13         while queue:
14             tmp = []
15             for i in range(len(queue)):
16                 node = queue.pop(0)
17                 tmp.append(node.val)
18                 if node.left:
19                     queue.append(node.left)
20                 if node.right:
21                     queue.append(node.right)
22             if tmp:
23                 depth += 1
24         return depth
View Code

  

dfs 實現,只須要記錄深度便可,不用記錄節點code

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     def TreeDepth(self, pRoot):
 8         # write code here
 9         if not pRoot:
10             return 0
11         self.depth = 0
12         def helper(node, level):
13             if not(node.left or node.right):
14                 self.depth = max(self.depth, level)
15                 return
16             if node.left:
17                 helper(node.left, level+1)
18             if node.right:
19                 helper(node.right, level+1)
20                 
21         helper(pRoot, 1)
22         return self.depth
View Code

  

 

3. 二叉樹的下一個節點blog

給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點而且返回。注意,樹中的結點不只包含左右子結點,同時包含指向父結點的指針。

解:

幾種可能的狀況考慮一下便可

 1 # class TreeLinkNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 #         self.next = None
 7 class Solution:
 8     def GetNext(self, pNode):
 9         # write code here
10         if not pNode:
11             return 
12         
13         # 若是當前節點有右子樹,中序遍歷的下一個節點是其右子樹的最左節點
14         if pNode.right:
15             pRight = pNode.right
16             while pRight.left:
17                 pRight = pRight.left
18             return pRight
19         
20         # 若是當前節點沒有右子樹,可是當前節點是其父節點的左子節點,下一個節點是其父節點
21         if pNode.next and pNode.next.left == pNode:
22             return pNode.next
23         
24         # 若是當前節點沒有右子樹,可是是其父節點的右子節點,則一直向上遍歷,找到是其父節點的左子結點的pNode
25         # 當前節點的下一個節點就是pNode的父節點
26         if pNode.next and pNode.next.right == pNode:
27             while pNode.next and pNode != pNode.next.left:
28                 pNode = pNode.next
29             return pNode.next
30         return 
View Code

  

 

4. 對稱的二叉樹

請實現一個函數,用來判斷一顆二叉樹是否是對稱的。注意,若是一個二叉樹同此二叉樹的鏡像是一樣的,定義其爲對稱的。

解:

遞歸實現,判斷給定兩個節點爲根的子樹是否鏡像,首先根節點的值要相等,其次A的左子樹和B的右子樹、A的右子樹和B的左子樹要遞歸的進行判斷

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     def isSymmetrical(self, pRoot):
 8         # write code here
 9         if not pRoot:
10             return True
11         return self.compare(pRoot.left, pRoot.right)
12     
13     def compare(self, p1, p2):
14         if p1 == None :
15             return p2 == None
16         if p2 == None:
17             return False
18         if p1.val != p2.val:
19             return False
20         return self.compare(p1.left, p2.right) and self.compare(p1.right, p2.left)
View Code

  

dfs,用棧實現,成對取出成對插入,鏡像:左左配右右,左右配右左

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     def isSymmetrical(self, pRoot):
 8         # write code here
 9         if not pRoot:
10             return True
11         stack = [pRoot.left, pRoot.right]
12         
13         while stack:
14             right = stack.pop()  # 成對取出
15             left = stack.pop()
16             if left == None and right == None:
17                 continue
18             if  left == None or right == None:
19                 return False
20             if left.val != right.val:
21                 return False
22             
23             # 成對插入
24             stack.append(left.left)
25             stack.append(right.right)
26             stack.append(left.right)
27             stack.append(right.left)
28             
29         return True
View Code

 

bfs,隊列實現

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     def isSymmetrical(self, pRoot):
 8         # write code here
 9         if not pRoot:
10             return True
11         queue = [pRoot.left, pRoot.right]
12         
13         while queue:
14             left = queue.pop(0)  # 成對取出
15             right = queue.pop(0)
16             if left == None and right == None:
17                 continue
18             if  left == None or right == None:
19                 return False
20             if left.val != right.val:
21                 return False
22             
23             # 成對插入
24             queue.append(left.left)
25             queue.append(right.right)
26             queue.append(left.right)
27             queue.append(right.left)
28             
29         return True
View Code

  

 

5. 把二叉樹打印成多行

從上到下按層打印二叉樹,同一層結點從左至右輸出。每一層輸出一行。

解:

層次遍歷,bfs

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     # 返回二維列表[[1,2],[4,5]]
 8     def Print(self, pRoot):
 9         # write code here
10         if not pRoot:
11             return []
12         res = []
13         queue = [pRoot]
14         while queue:
15             tmp = []
16             for i in range(len(queue)):
17                 node = queue.pop(0)
18                 tmp.append(node.val)
19                 if node.left:
20                     queue.append(node.left)
21                 if node.right:
22                     queue.append(node.right)
23             if tmp:
24                 res.append(tmp)
25         return res 
View Code

  

dfs

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     # 返回二維列表[[1,2],[4,5]]
 8     def Print(self, pRoot):
 9         # write code here
10         if not pRoot:
11             return []
12         self.res = []
13         
14         def helper(node, level):
15             if not node:
16                 return 
17             if level == len(self.res):
18                 self.res.append([])
19             self.res[level].append(node.val)
20             if node.left:
21                 helper(node.left, level + 1)
22             if node.right:
23                 helper(node.right, level + 1)
24 
25         helper(pRoot, 0)
26         return self.res 
View Code

  

 

6. 按之字形順序打印二叉樹

請實現一個函數按照之字形打印二叉樹,即第一行按照從左到右的順序打印,第二層按照從右至左的順序打印,第三行按照從左到右的順序打印,其餘行以此類推。

解:

仍是層次遍歷,用一個 flag 控制每一層是正序仍是逆序

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     def Print(self, pRoot):
 8         # write code here
 9         if not pRoot:
10             return []
11         leftToRight = True
12         queue = [pRoot]
13         res = []
14         while queue:
15             tmp = []
16             for i in range(len(queue)):
17                 node = queue.pop(0)
18                 tmp.append(node.val)
19                 if node.left:
20                     queue.append(node.left)
21                 if node.right:
22                     queue.append(node.right)
23             if tmp:
24                 if leftToRight:
25                     res.append(tmp)
26                 else:
27                     res.append(tmp[::-1])
28                 leftToRight = not leftToRight
29         return res
View Code

 

 

7. 序列化二叉樹

請實現兩個函數,分別用來序列化和反序列化二叉樹
二叉樹的序列化是指:把一棵二叉樹按照某種遍歷方式的結果以某種格式保存爲字符串,從而使得內存中創建起來的二叉樹能夠持久保存。序列化能夠基於先序、中序、後序、層序的二叉樹遍歷方式來進行修改,序列化的結果是一個字符串,序列化時經過 某種符號表示空節點(#),以 ! 表示一個結點值的結束(value!)。
二叉樹的反序列化是指:根據某種遍歷順序獲得的序列化字符串結果str,重構二叉樹。
解:
這題的序列化就直接前序遍歷實現便可,注意按要求用字符 # 和 !表示空節點和結束符。
主要問題在反序列化上,仍是按照根左右的順序遞歸,用 flag 來控制遞歸過程當中,反序列化的節點值在數組中的索引,flag從0開始,每次都+1,遇到‘#’說明是空節點,不須要構造node
 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     def __init__(self):
 8         self.flag = -1
 9     def Serialize(self, root):
10         # write code here
11         if not root:
12             return '#!'
13         return str(root.val)+'!'+self.Serialize(root.left)+self.Serialize(root.right)
14         
15     def Deserialize(self, s):
16         # write code here
17         self.flag += 1
18         vals = s.split('!')
19         if self.flag >= len(vals):
20             return None
21         root = None
22         if vals[self.flag] != '#':
23             root = TreeNode(int(vals[self.flag]))
24             root.left = self.Deserialize(s)
25             root.right = self.Deserialize(s)
26         return root
View Code

 

 

8. 二叉搜索樹的第k個節點

給定一棵二叉搜索樹,請找出其中的第k小的結點。例如, (5,3,7,2,4,6,8)    中,按結點數值大小順序第三小結點的值爲4。

解:

中序遍歷即有序

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     # 返回對應節點TreeNode
 8     def KthNode(self, pRoot, k):
 9         # write code here
10         if not pRoot:
11             return None
12         self.res = []
13         self.midOrdTrav(pRoot)
14         return self.res[k-1] if 0<k<=len(self.res) else None
15     
16     def midOrdTrav(self, root):
17         if not root:
18             return
19         self.midOrdTrav(root.left)
20         self.res.append(root)
21         self.midOrdTrav(root.right)
View Code

  

中序遍歷的時候維護一個計數器,到 k 個數了就返回

 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     # 返回對應節點TreeNode
 8     def KthNode(self, pRoot, k):
 9         # write code here
10         if not pRoot:
11             return None
12         
13         count = 0
14         stack = []
15         p = pRoot
16         while p or stack:
17             while p:
18                 stack.append(p)
19                 p = p.left
20             if stack:
21                 p = stack.pop()
22                 count += 1
23                 if count == k:
24                     return p
25                 p = p.right
26         return None
View Code

 

 
9.數據流中的中位數
如何獲得一個數據流中的中位數?若是從數據流中讀出奇數個數值,那麼中位數就是全部數值排序以後位於中間的數值。若是從數據流中讀出偶數個數值,那麼中位數就是全部數值排序以後中間兩個數的平均值。咱們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數。
解:
維護兩個堆,大頂堆用來存較小的數,從大到小排列;小頂堆用來存較大的數,從小到大排列。
保證小頂堆中的元素都大於等於大頂堆中的元素(始終保證較大數的那一半多一個或者同樣多,中位數始終在這一邊),因此 insert 的時候先 push 進小頂堆(存較大的數),再把小頂堆中的最小值 pop 出來 push 到大頂堆(存較小的數)中。
每次都檢查,若是小頂堆的元素個數小於大頂堆的元素個數(較大的數比較小的數少了),就把大頂堆中的最大值 pop 出來 push 小頂堆。
取中位數的時候,若是當前兩個堆同樣多,顯然是取小頂堆和大頂堆根結點的平均值;若是當前小頂堆元素個數多一個,顯然是取小頂堆的根節點
 1 import heapq
 2 class Solution:
 3     def __init__(self):
 4         self.small = []  # 小的數,大頂堆
 5         self.large = []  # 大的數,小頂堆
 6         
 7     def Insert(self, num):
 8         # write code here
 9         heapq.heappush(self.small, -heapq.heappushpop(self.large, num))
10         if len(self.large) < len(self.small):
11             heapq.heappush(self.large, -heapq.heappop(self.small))
12             
13     def GetMedian(self, default=None):
14         # write code here
15         if len(self.large) > len(self.small):
16             return float(self.large[0])
17         return (self.large[0] - self.small[0])/2.
View Code

  

 
10. 重建二叉樹
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
解:
其實就是一個遞歸的過程,每次找一下根節點在哪,進而定位好左右子樹的切片,構建好了根節點以後再分別去構建左右子樹
 1 # class TreeNode:
 2 #     def __init__(self, x):
 3 #         self.val = x
 4 #         self.left = None
 5 #         self.right = None
 6 class Solution:
 7     # 返回構造的TreeNode根節點
 8     def reConstructBinaryTree(self, pre, tin):
 9         # write code here
10         if not pre or not tin:
11             return None
12         root = TreeNode(pre[0]) 
13         index = self.Search(tin, root.val)  # tin.index(root.val)
14         root.left = self.reConstructBinaryTree(pre[1:index+1], tin[:index])
15         root.right = self.reConstructBinaryTree(pre[index+1:], tin[index+1:])
16         return root
17     
18     def Search(self, nums, target):
19         if not nums:
20             return -1
21         n = len(nums)
22         for i in range(n):
23             if nums[i] == target:
24                 return i
25         return -1
View Code
相關文章
相關標籤/搜索