3 分钟阅读

困难算法题,二叉树的最大路径和,使用 JavaScript 语言编写

题目

二叉树中的“路径”被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中至多出现一次。该路径至少包含一个节点,且不一定经过根节点。

“路径和”是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其最大路径和。

输入格式

树上的节点数满足 0 <= n <= 1000, 每个节点的值满足 -1000 <= val <= 1000

(注:null节点的左右叶子不会再打印 null)

输出格式

输出最大路径的和

输入样例

-10,9,20,null,null,15,7

输出样例

42

分析

要实现这个算法,我们可以使用递归的方法来遍历二叉树,并在每个节点计算包含该节点的最大路径和。我们需要一个辅助函数来计算从当前节点出发的最大路径和,同时更新全局最大路径和。

解答


// 这是题目要求的输入格式
let inputs = `
-10,9,20,null,null,15,7
`;
const nodes = inputs.trim().split(',').map(num => isNaN(num) ? null : parseInt(num));

class TreeNode {
  constructor(val, left = null, right = null) {
    this.val = val;
    this.left = left;
    this.right = right;
  }
}

function buildTree(nodes) {
  if (!nodes.length) return null;
  const root = new TreeNode(nodes[0]);
  const queue = [root];
  let i = 1;
  while (i < nodes.length) {
    const current = queue.shift();
    if (nodes[i] !== null) {
      current.left = new TreeNode(nodes[i]);
      queue.push(current.left);
    }
    i++;
    if (i < nodes.length && nodes[i] !== null) {
      current.right = new TreeNode(nodes[i]);
      queue.push(current.right);
    }
    i++;
  }
  return root;
}

function maxPathSum(root) {
  let maxSum = -Infinity;

  function maxGain(node) {
    if (node === null) {
      return 0;
    }

    // 递归计算左右子树的最大路径和
    const leftGain = Math.max(maxGain(node.left), 0);
    const rightGain = Math.max(maxGain(node.right), 0);

    // 计算经过当前节点的路径和
    const currentPathSum = node.val + leftGain + rightGain;

    // 更新全局最大路径和
    maxSum = Math.max(maxSum, currentPathSum);

    // 返回从当前节点出发的最大路径和, 因为如果当前节点不是最终路径的根节点, 那么只能选择左子树或者右子树,不能同时选择
    return node.val + Math.max(leftGain, rightGain);
  }

  maxGain(root);
  return maxSum;
}

// 示例
const root = buildTree(nodes);
console.log(maxPathSum(root)); // 输出 42

留下评论