二叉树
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))
要注意测试用例边界值的设计以及整型溢出等问题,构建二叉树,将数组转化为二叉树的形式等~