# -*- coding:UTF-8 -*-
import collections
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def maxDepth(root):
if root is None:
return 0
left = maxDepth(root.left)
right = maxDepth(root.right)
return max(left, right) + 1
def minDepth(root):
if root is None:
return 0
leftDepth = minDepth(root.left)
rightDepth = minDepth(root.right)
if root.left is None or root.right is None:
return max(leftDepth, rightDepth) + 1
return min(leftDepth, rightDepth) + 1
def numOfTreeNode(root):
if root is None:
return 0
left = numOfTreeNode(root.left)
right = numOfTreeNode(root.right)
return left + right + 1
def numsOfNoChildNode(root):
if root is None:
return 0
if (root.left is None and root.right is None):
return 1
return numsOfNoChildNode(root.left) + numsOfNoChildNode(root.right)
def numsOfkLevelTreeNode(root, k):
if root is None or k < 1:
return 0
if k == 1:
return 1
numsLeft = numsOfkLevelTreeNode(root.left, k - 1)
numsRight = numsOfkLevelTreeNode(root.right, k - 1)
return numsLeft + numsRight
def isBalanced(root):
return maxDeath2(root) != -1
def maxDeath2(root):
if root is None:
return 0
left = maxDeath2(root.left)
right = maxDeath2(root.right)
if (left == -1 or right == -1 or abs(left - right) > 1):
return -1
return max(left, right) + 1
def isCompleteTreeNode(root):
if root is None:
return False
queue = collections.deque()
queue.append(root)
result = True
hasNoChild = False
while (queue):
current = queue.popleft()
if (hasNoChild):
if (current.left != None or current.right != None):
result = False
break
else:
if (current.left != None and current.right != None):
queue.append(current.left)
queue.append(current.right)
elif (current.left != None and current.right == None):
queue.append(current.left)
hasNoChild = True
elif (current.left == None and current.right != None):
result = False
break
else:
hasNoChild = True
return result
def isSameTreeNode(t1, t2):
if (t1 is None and t2 is None):
return True
elif (t1 is None or t2 is None):
return False
if (t1.val != t2.val):
return False
left = isSameTreeNode(t1.left, t2.left)
right = isSameTreeNode(t1.right, t2.right)
return left and right
def mirrorTreeNode(root):
if root is None:
return 0
left = mirrorTreeNode(root.left)
right = mirrorTreeNode(root.right)
root.left = right
root.right = left
return root
# def getLastCommonParent(root, t1, t2):
# if (findNode(root.left, t1)):
# if (findNode(root.right, t2)):
# return root
# else:
# return getLastCommonParent(root.left, t1, t2)
# else:
# if (findNode(root.left, t2)):
# return root
# else:
# return getLastCommonParent(root.right, t1, t2)
#
#
# def findNode(root, node):
# if (root is None or node is None):
# return False
# if (root == node):
# return True
# found = findNode(root.left, node)
# if (not found):
# found = findNode(root.right, node)
# return found
"""
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
_______6______
/ \
___2__ ___8__
/ \ / \
0 _4 7 9
/ \
3 5
For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. Another example is LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.
"""
"""注意這裏是一個二叉搜索樹,根結點的右子樹上所有的點的值都比根結點大,左子樹上所有點的值都比根結點的值小
因此分爲四種情況,
1、如果兩個節點一個值比節點大,一個小,那麼二者的公共節點肯定是根結點,
2、如果兩個節點中有一個與根結點的值同樣大,那麼二者的公共節點同樣是根結點
3、如果兩個節點的值都比根結點小,那麼二者的公共節點出現在根結點的左子樹中,遞歸查詢
4、如果兩個節點的值都比根結點大,那麼二者的公共節點出現在根結點的右子樹中,遞歸查詢
"""
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
if (p.val - root.val) * (q.val - root.val) <= 0:
return root
if p.val < root.val and q.val < root.val:
return self.lowestCommonAncestor(root.left, p, q)
if p.val > root.val and q.val > root.val:
return self.lowestCommonAncestor(root.right, p, q)
# 廣度優先遍歷算法
def level_queue(root):
if root is None:
return
my_queue = collections.deque()
node = root
my_queue.append(node)
while my_queue:
node = my_queue.popleft()
print(node.val)
if node.left is not None:
my_queue.append(node.left)
if node.right is not None:
my_queue.append(node.right)
# 深度優先遍歷算法
def depth_tree(tree_node):
if tree_node is not None:
print(tree_node.val)
if tree_node.left is not None:
depth_tree(tree_node.left)
if tree_node.right is not None:
depth_tree(tree_node.right)
"""
二叉堆本質上是一種完全二叉樹,它分爲兩個類型:
1.最大堆
2.最小堆
對於二叉堆,如下有幾種操作:
1.插入節點
2.刪除節點
3.構建二叉堆 : 本質上就是讓所有非葉子節點依次下沉。
1
/ \
3 2
/ \ / \
6 5 7 8
/\
9 10
==> 1 3 2 6 5 7 8 9 10
假設父節點的下標是parent,那麼它的左孩子下標就是 2*parent+1;它的右孩子下標就是 2*parent+2 。
舉例 小根堆:
"""
def unAdjust(array):
childIndex = len(array) - 1
parentIndex = childIndex / 2
temp = array[childIndex]
while (childIndex > 0 and temp < array[parentIndex]):
array[childIndex] = array[parentIndex]
childIndex = parentIndex
parentIndex = parentIndex / 2
array[parentIndex] = temp
def downAdjust(array, parentIndex, length):
temp = array[parentIndex]
childIndex = 2 * parentIndex + 1
while (childIndex < length):
if childIndex + 1 < length and array[childIndex + 1] < array[childIndex]:
childIndex += 1
if temp <= array[childIndex]:
break
array[parentIndex] = array[childIndex]
parentIndex = childIndex
childIndex = 2 * childIndex + 1
array[parentIndex] = temp
def buildHeap(array):
for i in range(len(array) / 2)[::-1]:
downAdjust(array, i, len(array))
"""
堆排序算法的步驟:
1. 把無序數組構建成二叉堆。
2. 循環刪除堆頂元素,移到集合尾部,調節堆產生新的堆頂。
大根堆
"""
def downAdjustBig(array, parentIndex, length):
temp = array[parentIndex]
childIndex = 2 * parentIndex + 1
while (childIndex < length):
if childIndex + 1 < length and array[childIndex + 1] > array[childIndex]:
childIndex += 1
if temp >= array[childIndex]:
break
array[parentIndex] = array[childIndex]
parentIndex = childIndex
childIndex = 2 * childIndex + 1
array[parentIndex] = temp
def heapSort(array):
# 1.構建二叉堆
for i in range(len(array) / 2)[::-1]:
downAdjustBig(array, i, len(array))
print(array)
# 2.循環刪除堆頂元素,移到集合尾部,調節堆產生新的堆頂
for i in range(len(array))[::-1]:
temp = array[i]
array[i] = array[0]
array[0] = temp
downAdjustBig(array, 0, i)
def inorderTraversal_recur(root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return inorderTraversal_recur(root.left) + [root.val] + inorderTraversal_recur(root.right)
def preorderTraversal_recur(root): ##前序遍歷
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return [root.val] + preorderTraversal_recur(root.left) + preorderTraversal_recur(root.right)
def postorderTraversal_recur(root): ##後序遍歷
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return postorderTraversal_recur(root.left) + postorderTraversal_recur(root.right) + [root.val]
"""
當前結點curr不爲None時,每一次循環將當前結點curr入棧;
當前結點curr爲None時,則出棧一個結點,且打印出棧結點的value值。
整個循環在stack和curr皆爲None的時候結束。"""
def inorderTraversal(self, root):
stack = []
sol = []
curr = root
while stack or curr:
if curr:
stack.append(curr)
curr = curr.left
else:
curr = stack.pop()
sol.append(curr.val)
curr = curr.right
return sol
"""
由於前序遍歷的順序是中左右,所以我們每次先打印當前結點curr,並將右子結點push到棧中,然後將左子結點設爲當前結點。
入棧和出棧條件(當前結點curr不爲None時,每一次循環將當前結點curr入棧;
當前結點curr爲None時,則出棧一個結點)以及循環結束條件
(整個循環在stack和curr皆爲None的時候結束)與中序遍歷一模一樣。
"""
def preorderTraversal(self, root): ## 前序遍歷
stack = []
sol = []
curr = root
while stack or curr:
if curr:
sol.append(curr.val)
stack.append(curr.right)
curr = curr.left
else:
curr = stack.pop()
return sol
"""
代碼的主體部分基本就是.right和.left交換了順序,
且後序遍歷在最後輸出的時候進行了反向(因爲要從 中右左 變爲 左右中 )
"""
def postorderTraversal(self, root): ## 後序遍歷
stack = []
sol = []
curr = root
while stack or curr:
if curr:
sol.append(curr.val)
stack.append(curr.left)
curr = curr.right
else:
curr = stack.pop()
return sol[::-1]
# 前序 中序 構建樹
def getTreePreMid(pre, mid):
if len(pre) == 0:
return None
if len(pre) == 1:
return TreeNode(pre[0])
root = TreeNode(pre[0])
root_index = mid.index(pre[0])
root.left = getTreePreMid(pre[1:root_index + 1], mid[:root_index])
root.right = getTreePreMid(pre[root_index + 1:], mid[root_index + 1:])
return root
# 前序 中序 構建後序
def getAfterFromPreMid(pre, mid, res):
if len(pre) == 0:
return
if len(pre) == 1:
res.append(pre[0])
return
root = pre[0]
root_index = mid.index(root)
getAfterFromPreMid(pre[1:root_index + 1], mid[:root_index], res)
getAfterFromPreMid(pre[root_index + 1:], mid[root_index + 1:], res)
res.append(root)
return res
if __name__ == '__main__':
"""
0
/ \
1 3
/ \
4 5
/ \
6
/ \
8 7
"""
root = TreeNode(0)
a = TreeNode(1)
b = TreeNode(3)
c = TreeNode(4)
d = TreeNode(5)
e = TreeNode(6)
f = TreeNode(7)
g = TreeNode(8)
root.left = a
root.right = b
a.left = c
a.right = d
c.left = e
e.right = f
e.left = g
# print maxDepth(root)
# print minDepth(root)
# print(numOfTreeNode(root))
# print(numsOfNoChildNode(root))
# print(numsOfkLevelTreeNode(root, 4))
# print(isBalanced(root))
# print(maxDeath2(root))
# print(isCompleteTreeNode(c))
# print getLastCommonParent(root, a, b)
print("##" * 20)
# level_queue(root)
# print depth_tree(root)
array = [7, 1, 3, 10, 5, 2, 8, 9, 6]
buildHeap(array)
print(array)
print("##" * 20)
arr = [1, 3, 2, 6, 5, 7, 8, 9, 10, 0]
heapSort(arr)
print(arr)
print("--" * 20)
res = inorderTraversal(root)
print(res)
Python刷題--Tree(最大深度/葉節點數/非葉節點數/第K層節點數/平衡二叉樹/完全二叉樹/鏡像樹/LCA公共祖先/BFS/DFS/二叉堆/堆排序/遞歸,非遞歸實現前序中序後序遍歷)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.