【陪伴式刷题】Day 15|二叉树|257.二叉树的所有路径(Binary Tree Paths)

377 阅读3分钟

刷题顺序按照代码随想录建议

题目描述

英文版描述

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

英文版地址

leetcode.com/problems/bi…

中文版描述

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

示例 1:

输入: root = [1,2,3,null,5] 输出: ["1->2->5","1->3"]

示例 2:

输入: root = [1] 输出: ["1"]

提示:

  • 树中节点的数目在范围 [1, 100]
  • -100 <= Node.val <= 100

中文版地址

leetcode.cn/problems/bi…

解题方法

递归法

/**
 * 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),最好情况下,当二叉树为平衡二叉树时,它的高度为 log⁡n,此时空间复杂度为 O((log⁡n)^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(log⁡n),最坏情况下树呈现链状,栈中会存在 n 个节点及其路径,每个节点的最大路径为 n,故空间复杂度为 O(n^2)