二叉樹
prac98 驗證二叉搜索樹(中等)
給定一個二叉樹,判斷其是否是一個有效的二叉搜索樹。
假設一個二叉搜索樹具有如下特徵:
節點的左子樹只包含小於當前節點的數。 節點的右子樹只包含大於當前節點的數。 所有左子樹和右子樹自身必須也是二叉搜索樹。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/validate-binary-search-tree
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
構造輔助函數helper(node,lower,higher),並採用遞歸左子樹和遞歸右子樹的方法。
# -*- encoding: utf-8 -*-
"""
@File : prac98.py
@Time : 2020/5/5 8:43 上午
@Author : zhengjiani
@Email : [email protected]
@Software: PyCharm
"""
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
def helper(node,lower=float('-inf'),upper=float('inf')):
if not node:
return True
val = node.val
if val <= lower or val >= upper:
return False
if not helper(node.val,val,upper):
return False
if not helper(node.val,lower,val):
return False
return True
return helper(root)
prac572 另一個樹的子樹
給定兩個非空二叉樹 s 和 t,檢驗 s 中是否包含和 t 具有相同結構和節點值的子樹。s 的一個子樹包括 s 的一個節點和這個節點的所有子孫。s 也可以看做它自身的一棵子樹。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/subtree-of-another-tree
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
採用先序遍歷轉化爲字符串,並判斷兩個字符串是否含有包含關係。
# -*- encoding: utf-8 -*-
"""
@File : prac572.py
@Time : 2020/5/7 3:03 下午
@Author : zhengjiani
@Email : [email protected]
@Software: PyCharm
"""
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
"""DFS序列上做串匹配,先序遍歷,加入null值"""
def isSubtree(self, s: TreeNode, t: TreeNode) -> bool:
ss = self.inorder(s)
st = self.inorder(t)
return st in ss
#先序遍歷
def inorder(self,root):
if not root:
return '#'
return '*'+str(root.val)+str(root.left)+str(root.right)
prac236 二叉樹的最近公共祖先
給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。
百度百科中最近公共祖先的定義爲:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示爲一個結點 x,滿足 x 是 p、q 的祖先且 x
的深度儘可能大(一個節點也可以是它自己的祖先)。”例如,給定如下二叉樹: root = [3,5,1,6,2,0,8,null,null,7,4]
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
最近公共祖先判別公式:
最近公共祖先(flson&&frson) || ((x==p ||x ==q)&&(flson||frson))
# -*- encoding: utf-8 -*-
"""
@File : prac236.py
@Time : 2020/5/10 9:29 上午
@Author : zhengjiani
@Email : [email protected]
@Software: PyCharm
"""
from collections import deque
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Tree(object):
def __init__(self):
self.root = None
# 使用列表構建二叉樹
def construct_tree(self,values=None):
if not values:
return None
self.root = TreeNode(values[0])
queue = deque([self.root])
leng = len(values)
nums = 1
while nums < leng:
node = queue.popleft()
if node:
node.left = TreeNode(values[nums]) if values[nums] else None
queue.append(node.left)
if nums + 1 <leng:
node.right = TreeNode(values[nums+1]) if values[nums+1] else None
queue.append(node.right)
nums += 1
nums += 1
class Solution:
"""
最近公共祖先(flson&&frson)||((x==p ||x ==q)&&(flson||frson))
遞歸,時間複雜度O(N),空間複雜度O(N)N是二叉樹的節點數,遞歸調用的棧深度取決於二叉樹的高度
"""
def __init__(self):
self.ans = None
def lowestCommonAncestor(self, root, p, q):
"""
:param root: TreeNode
:param p: TreeNode
:param q: TreeNode
:return:
"""
self.dfs(root,p,q)
return self.ans
def dfs(self,root,p,q):
"""
:param root: TreeNode
:param p: TreeNode
:param q: TreeNode
:return: boolean
"""
if root is None:
return False
lson = self.dfs(root.left,p,q)
rson = self.dfs(root.right,p,q)
if (lson and rson) or ((root.val == p.val or root.val == q.val) and (lson or rson)):
self.ans = root
return lson or rson or (root.val == p.val or root.val == q.val)
class Solution1:
"""
存儲父節點使用哈希表
- 從根節點開始遍歷整棵二叉樹,用哈希表記錄每個節點的父節點指針
- 從p節點開始不斷往它的祖先移動,並用數據結構記錄已經訪問過的祖先節點
- 同樣,再從q節點開始不斷往它的祖先移動,如果有祖先已經被訪問過,意味着這是p和q深度最深的公共祖先,即LCA節點
"""
def __init__(self):
self.parent = {}
self.visited = set()
def lowestCommonAncestor(self, root, p, q):
self.dfs(root)
while p is not None:
self.visited.add(p.val)
p = self.parent.get(p.val)
while q is not None:
if q.val in self.visited:
return q
q = self.parent.get(q.val)
def dfs(self,root):
"""
:param root: TreeNode
:return:
"""
if root.left is not None:
self.parent[root.left.val] = root
self.dfs(root.left)
if root.right is not None:
self.parent[root.right.val] = root
self.dfs(root.right)
if __name__ == '__main__':
t = Tree()
t.construct_tree([3,5,1,6,2,0,8,None,None,7,4])
p = TreeNode(5)
q = TreeNode(1)
s = Solution()
print(s.lowestCommonAncestor(t.root,p,q).val)
數學計算
prac69 x的平方根
實現 int sqrt(int x) 函數。
計算並返回 x 的平方根,其中 x 是非負整數。
由於返回類型是整數,結果只保留整數的部分,小數部分將被捨去。
來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/sqrtx
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
# -*- encoding: utf-8 -*-
"""
@File : prac69.py
@Time : 2020/5/9 10:45 上午
@Author : zhengjiani
@Email : [email protected]
@Software: PyCharm
"""
class Solution:
"""二分查找"""
def mySqrt(self, x: int) -> int:
if x == 0:
return 0
left = 1
right = x // 2
while left < right:
#取右中位數
mid = (left + right + 1) >> 1
square = mid * mid
if square > x:
right = mid - 1
else:
left = mid
return left
class Solution1:
"""牛頓法
可以得到正實數的算術平方根,將牛頓法得到的浮點數轉化爲整數
思想:在迭代過程中,以直線代替曲線,用一階泰勒展開式(即當前點的切線)代替原曲線,求直線與x軸的交點,重複這個過程直到收斂
"""
def mySqrt(self, x: int) -> int:
if x < 0:
raise Exception('不能輸入負數')
if x == 0:
return 0
cur = 1
while True:
pre = cur
cur = (cur + x/cur)/2
if abs(cur-pre) < 1e-6:
return int(cur)
if __name__ == '__main__':
x = 8
s = Solution1()
print(s.mySqrt(x))
prac50 Pow(x,n),計算x的n次冪函數
# -*- encoding: utf-8 -*-
"""
@File : prac50.py
@Time : 2020/5/11 9:47 上午
@Author : zhengjiani
@Email : [email protected]
@Software: PyCharm
"""
class Solution:
"""快速冪算法
測試用例設計
- x = 0,1的情況
- n = 0,1的情況
- 測試n爲負數的情況
- 是否需要考慮溢出(Double數越界的情況)INT_MIN
- 其他正常測試
"""
def myPow(self, x: float, n: int) -> float:
def quickMul(N):
if N == 0:
return 1.0
y = quickMul(N//2)
return y*y if N%2 == 0 else y*y*x
return quickMul(n) if n >= 0 else 1/quickMul(-n)
class Solution1:
"""快速冪+迭代
以x^77爲例,每個額外乘的x都會被平方若干次,而這些指數1,4,8和64,恰好對應了77的二進制(1001101)2表示中的每個1
"""
def myPow(self, x: float, n: int) -> float:
def quickMul(N):
ans = 1.0
# 貢獻的初始值爲x
x_contribute = x
# 在對N進行二進制拆分的同時計算答案
while N > 0:
if N % 2 == 1:
# 如果N二進制表示的最低位爲1,那麼需要計入貢獻
ans *= x_contribute
# 將貢獻不斷的平方
x_contribute *= x_contribute
# 捨棄N二進制表示的最低位,這樣我們每次只要判斷最低位即可
N // 2
return ans
return quickMul(n) if n >= 0 else 1.0 / quickMul(-n)
if __name__ == '__main__':
x,n = 2.00000, 10
s = Solution()
print(s.myPow(x,n))
要注意測試用例邊界值的設計以及整型溢出等問題,構建二叉樹,將數組轉化爲二叉樹的形式等~