
本文共 5722 字,大约阅读时间需要 19 分钟。
树的路径
1、 二叉树的所有路径(257)
题目描述:
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
题解一:递归
# Definition for a binary tree node.# class TreeNode(object):# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass 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 = Noneclass 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 = Noneclass 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 = Noneclass 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 = Noneclass 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) 。
发表评论
最新留言
关于作者
