[前端]_一起刷leetcode 979. 在二叉树中分配硬币

480 阅读3分钟

这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战

题目

979. 在二叉树中分配硬币

给定一个有 N 个结点的二叉树的根结点 root,树中的每个结点上都对应有 node.val 枚硬币,并且总共有 N 枚硬币。

在一次移动中,我们可以选择两个相邻的结点,然后将一枚硬币从其中一个结点移动到另一个结点。(移动可以是从父结点到子结点,或者从子结点移动到父结点。)。

返回使每个结点上只有一枚硬币所需的移动次数。

 

示例 1:

输入: [3,0,0]
输出: 2
解释: 从树的根结点开始,我们将一枚硬币移到它的左子结点上,一枚硬币移到它的右子结点上。

示例 2:

输入: [0,3,0]
输出: 3
解释: 从根结点的左子结点开始,我们将两枚硬币移到根结点上 [移动两次]。然后,我们把一枚硬币从根结点移到右子结点上。

示例 3:

输入: [1,0,2]
输出: 2

示例 4:

输入: [1,0,0,null,3]
输出: 4

提示:

  1. 1<= N <= 100
  2. 0 <= node.val <= N

思路

  • 首先我们如果自上而下进行遍历的话,我们没办法确定当前元素有多的硬币的话,要丢给左边还是丢给右边,所以我们只能自下而上的查找才能达到最快的性能;

  • 还是老规矩,树的问题转换为递归问题,那么我们如何确定递归函数的函数体,也就是要在每个节点做点什么事情:

    • 首先先获取左右子节点的剩余硬币,这个值可能是正的或者负的,因为子节点不够的话可以从父节点获取,子节点多了也可以丢给父节点处理;

    • 其次获取完左右节点的剩余数量后,我们要减一,这个一是当前节点自己用掉的,然后如果这个值用掉了一后还有剩余或者不足,这时候我们就需要移动节点了,这里记得不管多了还是少了,我们要移动的数量都是取个绝对值;

    • 最后处理完了后把当前的节点剩余的数量返回给父节点使用即可。

  • 然后在代码层面上我们就只需要递归去遍历我们的根节点,然后计算有多少个硬币需要被移动多少次即可。

实现

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var distributeCoins = function(root) {
    // 记录移动的总次数
    let result = 0;

    // 判断当前节点有多少个硬币需要移动的, 或者需要移动多少个硬币过来
    function findChildCount(node) {
        // 节点非空判断
        if (!node) return 0;

        // 左右节点所剩余的数量, 减去自身消耗掉一个硬币
        node.val += findChildCount(node.left) + findChildCount(node.right) - 1;
        
        // 剩下的部分就需要被移动, 记得取绝对值
        result += Math.abs(node.val);

        // 用完的给父节点继续用
        return node.val;
    }


    findChildCount(root);

    return result;
};

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。