LeetCode之二叉树的所有路径(257)、路径总和(112、113、437)、二叉树的直径(543)

11 篇文章 0 订阅

1、 二叉树的所有路径(257)

题目描述:

给定一个二叉树,返回所有从根节点到叶子节点的路径。

说明: 叶子节点是指没有子节点的节点。

示例:

在这里插入图片描述

题目链接

题解一:递归

# 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 binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        def construct_paths(root, path):
            if root:
                path += str(root.val)
                if not root.left and not root.right:  # 当前节点是叶子节点
                    paths.append(path)  # 把路径加入到答案中
                else:
                    path += '->'  # 当前节点不是叶子节点,继续递归遍历
                    construct_paths(root.left, path)
                    construct_paths(root.right, path)

        paths = []
        construct_paths(root, '')
        return paths

2、路径总和(112)—判断路径和是否等于一个数

题目描述:

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 sum = 22,
在这里插入图片描述
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

题目链接

题解一:递归
思路:

1、寻找一条以root为根的、总和等于sum的路径可以分解为寻找一条以root.left为根或者以root.right为根的、总和等于sum - root.val的路径。
2、随着递归,每经过一个路径上一个非叶子节点,要寻找的值就减去了当前节点的值;
3、当到达叶子节点时,已经构成一条完整路径,此时若要寻找的值恰好和叶子节点的值相同,说明找到了一条这样的路径。

# 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 hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if root is None:#根结点为空
            return False
        if not root.left and not root.right:#根结点没有左右孩子
           return sum==root.val
        return self.hasPathSum(root.left,sum-root.val) or self.hasPathSum(root.right,sum-root.val)

在这里插入图片描述

  • 时间复杂度: O ( N ) O(N) O(N),其中 N N N 是树的节点数。对每个节点访问一次。

  • 空间复杂度: O ( H ) O(H) O(H),其中 H H H 是树的高度。空间复杂度主要取决于递归时栈空间的开销,最坏情况下,树呈现链状,空间复杂度为 O ( N ) O(N) O(N)。平均情况下树的高度与节点数的对数正相关,空间复杂度为 O ( log ⁡ N ) O(\log N) O(logN)

题解二:广度优先搜索/迭代
思路:

\quad \quad BFS 使用,存储将要遍历的节点,以及剩余路径和。如果该节点恰好是叶子节点,并且 路径和 正好等于 sum,说明找了解。

# 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 hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root: return False
        
        stack = [(root, sum - root.val)]
        while stack:
            cur_node, cur_sum = stack.pop()
            if not cur_node.left and not cur_node.right and cur_sum == 0:
                return True
            if cur_node.left:
                stack.append((cur_node.left, cur_sum - cur_node.left.val))
            if cur_node.right:
                stack.append((cur_node.right, cur_sum - cur_node.right.val))
        return False     
  • 时间复杂度: O ( N ) O(N) O(N),其中 N N N 是树的节点数。对每个节点访问一次。

  • 空间复杂度: O ( N ) O(N) O(N),其中 N N N 是树的节点数。

3、路径总和II(113)—找到所有路径总和等于给定目标和的路径。

题目描述:

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 sum = 22,

在这里插入图片描述
题目链接

题解一:深度优先搜索之递归

# 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 pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: List[List[int]]
        """
        self.result=[]
        if not root:
            return []
        
        def dfs(root,tmp,sum):
            if not root:
                return
            #叶子节点且值等于给定值
            if not root.left and not root.right and root.val==sum:
                tmp+=[root.val]
                self.result.append(tmp)
            dfs(root.left,tmp+[root.val],sum-root.val)
            dfs(root.right,tmp+[root.val],sum-root.val)
           
        dfs(root,[],sum)
        return self.result

4、路径总和III(437)—统计路径和等于给定数的路径总量

题目描述:

【中等】

给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。

路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。

示例:

在这里插入图片描述

题目链接

思路分析

1、注意路径不一定以 根结点开头,也不一定以 叶子节点结尾,但是必须连续。

2、

题解一:深度优先搜索之递归

5、二叉树的直径(543)

题目描述:

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
示例 :
给定二叉树
在这里插入图片描述
返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
注意:两结点之间的路径长度是以它们之间边的数目表示。

题目链接

知识点

1、路径长度
\quad \quad 如果树的结点序列 n 1 , n 2 , . . . , n k n_1,n_2,...,n_k n1,n2,...,nk有如下关系:结点 n i n_i ni n i + 1 n_i+1 ni+1的双亲(1<=i<k),则把 n 1 , n 2 , . . . , n k n_1,n_2,...,n_k n1,n2,...,nk称为一条由 n i n_i ni n k n_k nk的路径,路径上经过的边的个数称为路径长度。

2、直径长度:

\quad \quad 一棵二叉树的直径长度是任意两个结点路径长度中的最大值。

树的基本术语

思路分析:

1、初想,二叉树的直径长度=左子树高度+右子树高度,直接求根结点的左子树高度,以及右子树高度,然后再将两者相加即可;
在这里插入图片描述
2、转而一想,如果直径长度不穿过根结点,就没办法想上面那样求了,应该考虑以任意一个结点为根的直径情况:左子树高度+右子树高度,然后再求其最大值即可。

在这里插入图片描述
3、左子树高度、右子树高度采用递归法求即可,思想见求树的深度这篇文章

# 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 diameterOfBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.result=0#结果初始化为0
        def depth(node):
            #如果为空结点,返回0
            if not node: return 0
            #左孩子为根的子树的高度
            L=depth(node.left)
            #右孩子为根的子树的高度
            R=depth(node.right)
            #更新结果为其最大值
            self.result=max(self.result,L+R)
            return max(L,R)+1
        depth(root)
        return self.result

复杂度分析

  • 时间复杂度: O ( N ) O(N) O(N),其中 N N N 为二叉树的节点数,即遍历一棵二叉树的时间复杂度,每个结点只被访问一次。

  • 空间复杂度: O ( H e i g h t ) O(Height) O(Height),其中 H e i g h t Height Height 为二叉树的高度。由于递归函数在递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,而递归的深度显然为二叉树的高度,并且每次递归调用的函数里又只用了常数个变量,所以所需空间复杂度为 O ( H e i g h t ) O(Height) O(Height)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值