数据结构与算法学习(4)——二叉树

题目

PS:下列题目均来自leetcode中灵神题单

938. 二叉搜索树的范围和

class Solution:
    def rangeSumBST(self, root: TreeNode, low: int, high: int) -> int:
        if not root:
            return 0
        if root.val > high:
            return self.rangeSumBST(root.left, low, high)
        if root.val < low:
            return self.rangeSumBST(root.right, low, high)
        return root.val + self.rangeSumBST(root.left, low, high) + self.rangeSumBST(root.right, low, high)

2385. 感染二叉树需要的总时间

class Solution:
    def amountOfTime(self, root: Optional[TreeNode], start: int) -> int:
        G=defaultdict(list)
        def dfs(root):
            if root:
                if root.left:
                    G[root.val].append(root.left.val)
                    G[root.left.val].append(root.val)
                    dfs(root.left)
                if root.right:
                    G[root.val].append(root.right.val)
                    G[root.right.val].append(root.val)
                    dfs(root.right)
        dfs(root)

        q = deque([[start, 0]])
        vis=set()
        vis.add(start)
        while q:
            val,time=q.popleft()
            for around in G[val]:
                if around not in vis:
                    q.append([around, time + 1])
                    vis.add(around)
        return time

112. 路径总和

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        def search(root,pathval):
            if not root:
                return False            
            pathval += root.val
            if not root.left and not root.right:
                return pathval == targetSum           
            return search(root.left,pathval) or search(root.right,pathval)      
        return search(root,0)
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        def search(root,sum):
            if not root:
                return False
            sum-=root.val

            if not root.left and not root.right:
                if sum==0:
                    return True
                return False
            
            return search(root.left,sum) or search(root.right,sum)
        return search(root,targetSum)

111. 二叉树的最小深度

"""
我认为比较重要的一个是
if not root.left or not root.right:
  return max(left_depth, right_depth)
return min(left_depth, right_depth)
用来判断是不是叶结点
如果not root.left or not root.right那么证明该结点为叶结点或者只有左子节点 or 右子节点
如果该结点为叶结点那么left_depth=right_depth
如果只有左子节点 or 右子节点那么应该是max(left_depth, right_depth)因为此时较小的length不是到叶结点的length而是
当前单子结点的结点的length
"""
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        def dfs(root,length):
            if not root:
                return length
            left_depth = dfs(root.left, length + 1)
            right_depth = dfs(root.right, length + 1)
            if not root.left or not root.right:
                return max(left_depth, right_depth)
            return min(left_depth, right_depth)
        return dfs(root, 0)

129. 求根节点到叶节点数字之和

"""
这里的重点是要注意到
if not root.left and not root.right:
  return int(path+str(root.val))
这一句,理由是如果去掉这一句的话只保留
if not root:
  return apth
那么到达叶结点的结果会被相加两次导致最后的答案是正确结果的两倍
比如对于叶结点node,node.left=null and node.right=null
那么就返回了两次path相加了两次
"""
class Solution:
    def sumNumbers(self, root: Optional[TreeNode]) -> int:
        def dfs(root,path):
            if not root:
                return 0
            if not root.left and not root.right:
                return int(path+str(root.val))
            return str(int(dfs(root.left,path+str(root.val)))+int(dfs(root.right,path+str(root.val))))
        
        return int(dfs(root,''))

1379. 找出克隆二叉树中的相同节点

#BFS
class Solution:
    def getTargetCopy(self, original: TreeNode, cloned: TreeNode, target: TreeNode) -> TreeNode:
        queue = deque([cloned])
        while queue:
            node=queue.popleft()
            if node.val==target.val:
                return node
            else:
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)

894. 所有可能的真二叉树

# 动态规划
"""
对于i个叶子
如果左侧有j(1->i-1)个叶子那么右侧i−j个叶子
注意我们这里遍历是叶子结点因为某一叶结点增加两个叶结点的时候减少了一个
那么总的数量只会增加一个
另外真二叉树的结点个数只会是奇数个
"""
Max=11
ft=[[] for _ in range(Max)]
ft[1]=[TreeNode()]
for i in range(2,Max):
    for j in range(1,i):
        for left in ft[j]:
            for right in ft[i-j]:
                ft[i].append(TreeNode(0,left,right))
class Solution:
    def allPossibleFBT(self, n: int) -> List[Optional[TreeNode]]:
        return ft[(n + 1) // 2] if n % 2 else []

226. 翻转二叉树

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        def dfs(dummy):
            if not dummy:
                return dummy
            left=dfs(dummy.left)
            right=dfs(dummy.right)
            dummy.left,dummy.right=right,left
            return dummy
        return dfs(root)

1261. 在受污染的二叉树中查找元素

class FindElements:

    def __init__(self, root: Optional[TreeNode]):
        root.val=0
        self.queue=deque([root])
        self.dummy=root
        while self.queue:
            node=self.queue.popleft()
            if not node.left and not node.right:
                continue
            v=node.val
            if node.left:
                node.left.val=2*v+1
                self.queue.append(node.left)
            if node.right:
                node.right.val=2*v+2
                self.queue.append(node.right)
    def find(self, target: int) -> bool:
        def dfs(root):
            if not root:
                return False
            if root.val==target:
                return True
            return dfs(root.left) or dfs(root.right)
        root=self.dummy
        return dfs(root)
#优化,在FindElements初始的时候就记录val,而不是重新检索
class FindElements:

    def __init__(self, root: Optional[TreeNode]):
        root.val=0
        self.queue=deque([root])
        self.dummy=root
        self.p=set()
        self.p.add(0)
        while self.queue:
            node=self.queue.popleft()
            if not node.left and not node.right:
                continue
            v=node.val
            if node.left:
                node.left.val=2*v+1
                self.p.add(node.left.val)
                self.queue.append(node.left)
            if node.right:
                node.right.val=2*v+2
                self.p.add(node.right.val)
                self.queue.append(node.right)
    def find(self, target: int) -> bool:
        return target in self.p

938. 二叉搜索树的范围和

class Solution:
    def rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
        queue=deque([root])
        res=0
        while queue:
            node=queue.popleft()
            if node.val >=low and node.val<=high:
                res+=node.val
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)  
        return res

2476. 二叉搜索树最近节点查询

# bisect_left返回的是大于等于该查询值的第一个数,我老是容易记混
class Solution:
    def closestNodes(self, root: Optional[TreeNode], queries: List[int]) -> List[List[int]]:
        ans=[]
        queue=deque([root])
        v=[]
        while queue:
            node=queue.popleft()
            v.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        n = len(v)
        ans = []
        v.sort()
        for q in queries:
            j = bisect_left(v, q)
            mx = v[j] if j < n else -1
            if j == n or v[j] != q:  # a[j]>q, a[j-1]<q
                j -= 1
            mn = v[j] if j >= 0 else -1
            ans.append([mn, mx])
        return ans
#bisect_left
if lo < 0:
    raise ValueError('lo must be non-negative')
if hi is None:
    hi = len(a)
while lo < hi:
    mid = (lo+hi)//2
    if a[mid] < x: lo = mid+1
    else: hi = mid
return lo

2583. 二叉树中的第 K 大层和

# 注意审题就好,很简单的BFS
def kthLargestLevelSum(self, root: Optional[TreeNode], k: int) -> int:
        queue=deque([(root,1)])
        res=dict()
        while queue:
            node,t=queue.popleft()
            if node.left:
                queue.append((node.left,t+1))
            if node.right:
                queue.append((node.right,t+1))
            if t in res:
                res[t]+=node.val
            else:
                res[t]=node.val
        s=sorted(res.items(), key = lambda kv:(kv[1], kv[0])) 
        if k>len(s):
            return -1  
        return s[-k][1] 

889. 根据前序和后序遍历构造二叉树

不会()
posted @ 2024-05-28 22:59  zddkk  阅读(6)  评论(0编辑  收藏  举报