刷题顺序按照代码随想录建议
题目描述
英文版描述
Given the root of a binary tree, return all root-to-leaf paths in any order.
A leaf is a node with no children.
Example 1:
Input: root = [1,2,3,null,5] Output: ["1->2->5","1->3"]
Example 2:
Input: root = [1] Output: ["1"]
Constraints:
- The number of nodes in the tree is in the range
[1, 100]. -100 <= Node.val <= 100
英文版地址
中文版描述
给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入: root = [1,2,3,null,5] 输出: ["1->2->5","1->3"]
示例 2:
输入: root = [1] 输出: ["1"]
提示:
- 树中节点的数目在范围
[1, 100]内 -100 <= Node.val <= 100
中文版地址
解题方法
递归法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> result = new ArrayList<>();
List<Integer> level = new ArrayList<>();
if (root == null) {
return result;
}
recursion(root, result, level);
return result;
}
private void recursion(TreeNode root, List<String> result, List<Integer> level) {
level.add(root.val);
if (root.left == null && root.right == null) {
String ll = conversionToString(level);
result.add(ll);
return;
}
TreeNode left = root.left;
if (left != null) {
recursion(left, result, level);
level.remove(level.size() - 1);
}
TreeNode right = root.right;
if (right != null) {
recursion(right, result, level);
level.remove(level.size() - 1);
}
}
private String conversionToString(List<Integer> level) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < level.size() - 1; i++) {
sb.append(level.get(i)).append("->");
}
sb.append(level.get(level.size() - 1));
return sb.toString();
}
}
复杂度分析
-
时间复杂度:O(n^2),其中 n 表示节点数目,在递归中每个节点会访问一次,并且每个节点都会生成以该节点为根节点的路径的字符串表示,假设树的深度为d,那么构造这样的字符串表示需要的时间复杂度为O(d),每一次会调用方法conversionToString(),该方法有一个for循环,其时间代价为 O(n),故时间复杂度为 O(n^2)
-
对于字符串的构造,我们需要遍历整个路径,也就是伪代码中的
List<Integer> level。遍历这个列表并将其转换成字符串的时间消耗是和路径长度(也就是树的深度d)成正比的,所以时间复杂度是O(d)。这是因为我们要对列表中的每一个元素进行操作(即,转换为字符串,并添加到StringBuilder对象sb中),这样的操作每一次都需要一定的时间,因此总的时间消耗将会随着列表长度的增加而增加。在这个代码的conversionToString()方法里,对于列表中的每一个元素,我们都执行了以下步骤:- 1)将元素转换成字符串
- 2)将字符串添加到StringBuilder对象sb中
因此,这个过程的时间复杂度基本上是O(d),其中d是列表的长度。
-
-
空间复杂度:O(n^2),其中 n 表示节点数目,除了递归栈需要的空间之外,还需要考虑存储生成的所有路径的空间,每一条路径可以看作一个长度不超过d的字符串,因此需要的空间为O(n*d)。在最坏情况下,当二叉树中每个节点只有一个孩子节点时,即整棵二叉树呈一个链状,此时递归的层数为 n,此时每一层的 level 变量转换为String的空间代价的总和为 O(n^2),最好情况下,当二叉树为平衡二叉树时,它的高度为 logn,此时空间复杂度为 O((logn)^2)
迭代法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> result = new ArrayList<>();
if (root == null) {
return result;
}
Stack<Object> stack = new Stack<>();
stack.add(root);
stack.add(root.val + "");
while (!stack.isEmpty()) {
String path = (String) stack.pop();
TreeNode node = (TreeNode) stack.pop();
if (node.left == null && node.right == null) {
result.add(path);
}
if (node.left != null) {
stack.push(node.left);
stack.push(path + "->" + node.left.val);
}
if (node.right != null) {
stack.push(node.right);
stack.push(path + "->" + node.right.val);
}
}
return result;
}
}
复杂度分析
- 时间复杂度:O(n^2),同递归法
- 空间复杂度:O(n^2),为迭代过程中栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,栈中会存在 n 个节点及其路径,每个节点的最大路径为 n,故空间复杂度为 O(n^2)