题目一:路径寻找

112. 路径总和

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

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

示例 1:
二叉树 - 图1
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true

示例 2:
二叉树 - 图2
输入:root = [1,2,3], targetSum = 5
输出:false

示例 3:
输入:root = [1,2], targetSum = 0
输出:false

提示:

树中节点的数目在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  1. /**
  2. * Definition for a binary tree node.
  3. * function TreeNode(val, left, right) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.left = (left===undefined ? null : left)
  6. * this.right = (right===undefined ? null : right)
  7. * }
  8. */
  9. /**
  10. * @param {TreeNode} root
  11. * @param {number} targetSum
  12. * @return {boolean}
  13. */
  14. var hasPathSum = function(root, targetSum) {
  15. const dfs = (node, t) => {
  16. // 叶子节点,满足条件t === node.val
  17. if (node && t === node.val && (!node.left && !node.right)) {
  18. return true;
  19. }
  20. if (node && dfs(node.left, t - node.val)) return true;
  21. if (node && dfs(node.right, t - node.val)) return true;
  22. return false;
  23. };
  24. return dfs(root, targetSum);
  25. };

变种一:返回结果集

路径总和 II https://leetcode-cn.com/problems/path-sum-ii

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

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

示例 1:
二叉树 - 图3
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

示例 2:
二叉树 - 图4
输入:root = [1,2,3], targetSum = 5
输出:[]

示例 3:
输入:root = [1,2], targetSum = 0
输出:[]

提示:

树中节点总数在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  1. /**
  2. * Definition for a binary tree node.
  3. * function TreeNode(val, left, right) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.left = (left===undefined ? null : left)
  6. * this.right = (right===undefined ? null : right)
  7. * }
  8. */
  9. /**
  10. * @param {TreeNode} root
  11. * @param {number} targetSum
  12. * @return {number[][]}
  13. */
  14. var pathSum = function(root, targetSum) {
  15. const ans = [];
  16. const dfs = (node, t, paths) => {
  17. // 叶子节点,满足条件t === node.val
  18. if (node && t === node.val && (!node.left && !node.right)) {
  19. paths.push(node.val);
  20. // 复制到结果集合中
  21. ans.push([...paths]);
  22. paths.pop();
  23. return true;
  24. }
  25. if (node) {
  26. // 与前一的差异是需要回溯,在左右两个子节点间遍历,因为是返回所有结果结果集。
  27. paths.push(node.val);
  28. dfs(node.left, t - node.val, paths);
  29. dfs(node.right, t - node.val, paths);
  30. // 回溯堆栈
  31. paths.pop();
  32. }
  33. return false;
  34. };
  35. dfs(root, targetSum, []);
  36. return ans;
  37. };

变种二:437. 路径总和 III

难度中等940收藏分享切换为英文接收动态反馈
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

示例 1:
二叉树 - 图5
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。

示例 2:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3


提示:

  • 二叉树的节点个数的范围是 [0,1000]
  • -109 <= Node.val <= 109
  • -1000 <= targetSum <= 1000
  1. /**
  2. * Definition for a binary tree node.
  3. * function TreeNode(val, left, right) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.left = (left===undefined ? null : left)
  6. * this.right = (right===undefined ? null : right)
  7. * }
  8. */
  9. /**
  10. * @param {TreeNode} root
  11. * @param {number} targetSum
  12. * @return {number}
  13. */
  14. var pathSum = function(root, targetSum) {
  15. if (!root) return 0;
  16. let ans = 0;
  17. const dfs = (node, t) => {
  18. if (!node) return;
  19. // 叶子节点,满足条件t === node.val,不要return,继续寻找,有可能后续会右多个节点之和为0.
  20. if (t === node.val) {
  21. ans++;
  22. }
  23. dfs(node.left, t - node.val);
  24. dfs(node.right, t - node.val);
  25. };
  26. dfs(root, targetSum);
  27. // 再以左右子树来遍历寻找。
  28. ans += pathSum(root.left, targetSum);
  29. ans += pathSum(root.right, targetSum);
  30. return ans;
  31. };

题目二: 子节点大小选择

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。

示例 1:
二叉树 - 图6
输入:root = [3,9,20,null,null,15,7]
输出:2

示例 2:
输入:root = [2,null,3,null,4,null,5,null,6]
输出:5


提示:

  • 树中节点数的范围在 [0, 105]
  • -1000 <= Node.val <= 1000
    1. /**
    2. * Definition for a binary tree node.
    3. * function TreeNode(val, left, right) {
    4. * this.val = (val===undefined ? 0 : val)
    5. * this.left = (left===undefined ? null : left)
    6. * this.right = (right===undefined ? null : right)
    7. * }
    8. */
    9. /**
    10. * @param {TreeNode} root
    11. * @return {number}
    12. */
    13. var minDepth = function(root) {
    14. const dfs = (node) => {
    15. if (!node) return 0;
    16. // 只有左子树,结果等 1 + h(left);
    17. if (node && !node.right) {
    18. return 1 + dfs(node.left);
    19. }
    20. // 只有右子树,结果等 1 + h(right);
    21. if (node && !node.left) {
    22. return 1 + dfs(node.right);
    23. }
    24. return Math.min(dfs(node.left), dfs(node.right)) + 1;
    25. };
    26. return dfs(root);
    27. };

题目类型三:有序性

114. 二叉树展开为链表
难度中等878收藏分享切换为英文接收动态反馈
给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。


    示例 1:
    二叉树 - 图7
    输入:root = [1,2,5,3,4,null,6]
    输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2:
输入:root = []
输出:[]

示例 3:
输入:root = [0]
输出:[0]


提示:

  • 树中结点数在范围 [0, 2000]
  • -100 <= Node.val <= 100


    进阶:你可以使用原地算法(O(1) 额外空间)展开这棵树吗?

解法一:递归

  1. /**
  2. * Definition for a binary tree node.
  3. * function TreeNode(val, left, right) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.left = (left===undefined ? null : left)
  6. * this.right = (right===undefined ? null : right)
  7. * }
  8. */
  9. /**
  10. * @param {TreeNode} root
  11. * @return {void} Do not return anything, modify root in-place instead.
  12. */
  13. var flatten = function(root) {
  14. let top; // 只使用栈顶指针
  15. const dfs = (node) => {
  16. if (!node) {
  17. return;
  18. }
  19. let left = node.left;
  20. let right = node.right;
  21. if (top) {
  22. // 关联右指针
  23. top.right = node;
  24. top.left = null;
  25. }
  26. // 入栈
  27. top = node;
  28. dfs(left);
  29. dfs(right);
  30. };
  31. dfs(root);
  32. return root;
  33. };

解法二: 三指针

  1. /**
  2. * Definition for a binary tree node.
  3. * function TreeNode(val, left, right) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.left = (left===undefined ? null : left)
  6. * this.right = (right===undefined ? null : right)
  7. * }
  8. */
  9. /**
  10. * @param {TreeNode} root
  11. * @return {void} Do not return anything, modify root in-place instead.
  12. */
  13. var flatten = function(root) {
  14. let curr = root;
  15. while (curr !== null) {
  16. // 左子树不为空
  17. if (curr.left !== null) {
  18. const next = curr.left;
  19. // 找到当前节点的左子树的最右节点,这个节点为pre。
  20. let pre = next;
  21. while (pre.right !== null) {
  22. pre = pre.right;
  23. }
  24. // 移动cur的右子树为pre的右子树。
  25. pre.right = curr.right;
  26. // 旋转左子树为右子树。
  27. curr.left = null;
  28. curr.right = next;
  29. }
  30. // 只有右子树,则继续跳跃指针
  31. curr = curr.right;
  32. }
  33. };