leetcode-树-v2

leetcode—hot100-树1_林冲风雪山神庙的博客-CSDN博客

100. 相同的树

class Solution(object):
    def isSameTree(self, p, q):
        """
        :type p: TreeNode
        :type q: TreeNode
        :rtype: bool
        """
        if p is None and q is None:
            return True
        if p is None and q is not None:
            return False
        if p is not None and q is None:
            return False
        if p.val!=q.val:
            return False
        else:
            return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)

101. 对称二叉树

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        def dfs(left,right):
            if not left and not right:
                return True
            if not left or not right:
                return False
            if left.val != right.val:
                return False
            return dfs(left.left,right.right) and dfs(left.right,right.left)
        return dfs(root.left,root.right)

        

226. 翻转二叉树

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if root is None:
            return
        self.invertTree(root.left)
        self.invertTree(root.right)
        left=root.left
        right=root.right
        root.left=right
        root.right=left
        return root

6018. 根据描述创建二叉树

看一下lru: lru也是用哈希表来存储,key是节点值,value是节点node

 

用哈希表记录以node为根节点,对应的节点值。为了找整个树的根用。

  for k in node.keys():
            if k not in c:
                return node[k]

 

 if x == 1:
                ns.left = ne
            else:
                ns.right = ne

会改变原哈希表的值

# 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:
    def createBinaryTree(self, descriptions: List[List[int]]) -> Optional[TreeNode]:
        def f(i):
            s, e, x = descriptions[i]
            c[e] = c.get(e, 0) + 1
            if s not in node:
                ns = TreeNode(s)
                node[s] = ns
            else:
                ns = node[s]
            if e not in node:
                ne = TreeNode(e)
                node[e] = ne
            else:
                ne = node[e]
            if x == 1:
                ns.left = ne
            else:
                ns.right = ne
        node = {}
        c = {}
        for i in range(len(descriptions)):
            f(i)
        for k in node.keys():
            if k not in c:
                return node[k]
        

作者:qin-qi-shu-hua-2
链接:https://leetcode-cn.com/problems/create-binary-tree-from-descriptions/solution/python-ha-xi-by-qin-qi-shu-hua-2-b768/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

树的路径问题

分为二叉树和多叉树

求树的直径:

  1. 二叉树的直径是当前节点的,左子树的最大深度,右边子树的最大深度,+1.在求二叉树的直径时,定义一个全局变量,在递归求树深的时候求出这个全局变量最大值。
  2. 多叉树的直径

543. 二叉树的直径

 力扣

class Solution:
    def diameterOfBinaryTree(self, root: TreeNode) -> int:
        self.ans = 1
        def depth(node):
            # 访问到空节点了,返回0
            if not node:
                return 0
            # 左儿子为根的子树的深度
            L = depth(node.left)
            # 右儿子为根的子树的深度
            R = depth(node.right)
            # 计算d_node即L+R+1 并更新ans
            self.ans = max(self.ans, L + R + 1)
            # 返回该节点为根的子树的深度
            return max(L, R) + 1

        depth(root)
        return self.ans - 1

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/diameter-of-binary-tree/solution/er-cha-shu-de-zhi-jing-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def diameterOfBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.ans = 0
        #肯定有一个公共父节点(不一定是根节点)
        def dfs(root):
            if root is None:
                return 0
            left = dfs(root.left) 
            right = dfs(root.right) 
            self.ans = max(left+right+1,self.ans)
            return max(left,right) + 1
        tmp_ans = dfs(root)
        return self.ans - 1

            

104. 二叉树的最大深度

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        def dfs(root):
            if not root:
                return 0
            left = dfs(root.left)
            right = dfs(root.right)
            return max(left,right)+1
        return dfs(root)

1245. 树的直径(多叉树)

方法1 两次遍历

第一次bfs一定会找到最长路径的一个端点。因为随机取一个点,搜到它的最远点时,一定会经过根节点。可把这条路径分为2段,first ->root ->remote. root->remote的距离一定是最长的。

第二次bfs的时候从remote开始,remote->root->anothor_remote.这样找到的就是整个图的最长路径。

方法2: 记录当前节点的最大路径和次大路径

最大路径 ->当前节点 ->次大路径,构成了一个以当前节点为父节点的最长路径。

class Solution(object):
    def treeDiameter(self, edges):
        """
        :type edges: List[List[int]]
        :rtype: int
        """
        self.ans = 0
        #先建图
        import collections
        graph = collections.defaultdict(list)
        for i in range(len(edges)):
            graph[edges[i][0]].append(edges[i][1])
            graph[edges[i][1]].append(edges[i][0])
         #难点在于从哪个节点开始遍历.
        # 从任意顶点开始遍历,在遍历时记录最大值和次大值。因为图是联通的,所以以任意节点开始。都可以遍历到所有节点
        def dfs(root,visited):
            neighbors = graph[root]
            d1,d2,d = 0,0,0
            for neighbor in neighbors:
                #防止往回遍历
                if neighbor in visited:
                    continue
                visited.add(neighbor)
                d = dfs(neighbor,visited)
                if d > d1:
                    d1,d2 = d,d1
                elif d > d2:
                    d2 = d
            self.ans = max(self.ans,d1+d2)
            return max(d1,d2) + 1
        visited = set()
        visited.add(0)
        ans_tmp = dfs(0,visited)
        return self.ans

124 二叉树中的最大路径和

返回当前节点的贡献最大值,当前节点的贡献最大值是 roo.val + max(left,right)

因为题目中要求的是序列,所以要返回的是单边最大贡献,这样子方便去进行递归。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def maxPathSum(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        #左边最大值 + 根 + 右边最大值,根,左边最大值 + 根,右边最大值+ 根 的最大值
        self.ans = float("-inf")
        def dfs(root):
            if not root:
                return 0
            left = dfs(root.left)
            right = dfs(root.right)
            self.ans = max(self.ans,left + root.val + right,root.val,left+root.val,right+root.val)
            # self.ans = max(self.ans,left + root.val + right)
            return max(root.val + max(left,right),root.val)
            # return max(left + root.val + right,root.val,left+root.val,right+root.val)
        ans_tmp = dfs(root)
        return self.ans
class Solution {
    int maxSum = Integer.MIN_VALUE;

    public int maxPathSum(TreeNode root) {
        maxGain(root);
        return maxSum;
    }

    public int maxGain(TreeNode node) {
        if (node == null) {
            return 0;
        }
        
        // 递归计算左右子节点的最大贡献值
        // 只有在最大贡献值大于 0 时,才会选取对应子节点
        int leftGain = Math.max(maxGain(node.left), 0);
        int rightGain = Math.max(maxGain(node.right), 0);

        // 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
        int priceNewpath = node.val + leftGain + rightGain;

        // 更新答案
        maxSum = Math.max(maxSum, priceNewpath);

        // 返回节点的最大贡献值
        return node.val + Math.max(leftGain, rightGain);
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/solution/er-cha-shu-zhong-de-zui-da-lu-jing-he-by-leetcode-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

6073. 相邻字符不同的最长路径

 

有case不通过。在遍历相邻节点的时候,不管是不是相同字符,都要进行遍历,不如后续情况可能会找不到。只有不同字符才更新距离,相同字符就不更新距离

class Solution(object):
    def longestPath(self, parent, s):
        """
        :type parent: List[int]
        :type s: str
        :rtype: int
        """
        #先建树,然后遍历树,在遍历的过程中记录最长路径和次长路径
        #递归函数返回 当前节点,和当前节点的单表最大值
        self.ans = 0
        import collections
        graph = collections.defaultdict(list)
        for i in range(len(parent)):
            graph[parent[i]].append(i)
        print(graph)

        def dfs(root,visited):
            neighbors  = graph[root]
            d,d1,d2 = 0,0,0
            for neighbor in neighbors:
                if s[neighbor] != s[root] and neighbor not in visited:
                    visited.add(neighbor)
                    d = dfs(neighbor,visited)
                    if d > d1 :
                        d1,d2 = d,d1 
                    elif d > d2 :
                        d2 = d 
            self.ans = max(self.ans,d1+d2+1)
            return max(d1,d2)+1
        visited = set()
        visited.add(-1)
        tmp_ans = dfs(0,visited)
        return self.ans
            
class Solution(object):
    def longestPath(self, parent, s):
        """
        :type parent: List[int]
        :type s: str
        :rtype: int
        """
        # 先建树,然后遍历树,在遍历的过程中记录最长路径和次长路径
        # 递归函数返回 当前节点,和当前节点的单表最大值
        self.ans = 0
        import collections
        graph = collections.defaultdict(list)
        for i in range(len(parent)):
            graph[parent[i]].append(i)
        def dfs(root, visited):
            neighbors = graph[root]
            d, d1, d2 = 0, 0, 0
            for neighbor in neighbors:
                if neighbor not in visited:
                    visited.add(neighbor)
                    d = dfs(neighbor, visited)
                    if s[root] == s[neighbor]:
                        continue
                    if d > d1:
                        d1, d2 = d, d1
                    elif d > d2:
                        d2 = d
            self.ans = max(self.ans, d1 + d2 + 1)
            return max(d1, d2) + 1
        visited = set()
        visited.add(0)
        tmp_ans = dfs(0,visited)
        return self.ans

236. 二叉树的最近公共祖先

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        #从底向上。这里的底不一定是到叶子结点,当搜到p或者q结点时就返回
        def dfs(root,p,q):
            if not root or root == p or root == q:
                return root 
            left = dfs(root.left,p,q)
            right = dfs(root.right,p,q)
            if left and right:
                return root
            elif left and not right:
                return left 
            elif right and not left:
                return right 
        return dfs(root,p,q)

979. 在二叉树中分配硬币

 

class Solution:
    def distributeCoins(self, root: TreeNode) -> int:        
        self.step = 0
        def dfs(node):
            if not node: return 0
            left = dfs(node.left)
            right = dfs(node.right)
            self.step += abs(left) + abs(right)
            return left + right + node.val - 1
        dfs(root)
        return self.step

作者:chenchuxin
链接:https://leetcode.cn/problems/distribute-coins-in-binary-tree/solution/hou-xu-bian-li-by-chenchuxin/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值