力扣每日一题2023.7.14在二叉树中分配硬币

题目:

力扣每日一题2023.7.14在二叉树中分配硬币_第1张图片

示例:

力扣每日一题2023.7.14在二叉树中分配硬币_第2张图片

力扣每日一题2023.7.14在二叉树中分配硬币_第3张图片

分析:

给一个二叉树,二叉树的值总和等于整个二叉树的节点数,我们一次可以移动一个节点的一个值到相邻节点,问我们需要移动多少次才可以把值的总和平均分配每个节点(即每个节点的值都为1).

我们可以确定的是,如果某个节点的左子树共有n个节点,而节点值总和为m,那么光这个节点的左子树就会有|n-m|个值会经过这个节点,我们虽然不知道|n-m|个值一共要移动多少次,但是光是与节点相邻的边就一定会要移动|n-m|次.以示例1为例,我们结合下图来说明一下:

力扣每日一题2023.7.14在二叉树中分配硬币_第4张图片

 以根节点的左节点为例,它没有左右子树,也就是说子树节点和为0,子树节点值总和也为0,二者相同,可以暂时不用管.而自己的值为0,但是自己需要有一个值,那也就只能从父节点给一个值过来,所以左节点和根节点之间的这条路径,会有一个值传递过来,也就是算作移动一次(即使还没有发生,但是我们可以预料到会发生,因此可以先加入到res中).

我们再看一下示例四:

力扣每日一题2023.7.14在二叉树中分配硬币_第5张图片

 最下面的值为3的节点,没有子树,自然也没有子树值总和,因此在子树这方面属于收支平衡,而自己的节点值为3,比1多2,因此它必须把两个值都传递给父节点,所以算是需要传递两次(res+=abs(2)).

再看一下左边的值为0的节点,该节点的子树节点数为1,而子树节点值总和为3,有2的盈余,但是自己的值为0,算是自身亏损1,再加上子树的盈余,因此总的有1的盈余,因此它必然有一个值要传递给它的父节点,所以算是要传递一次(res+=abs(1)).

再复杂的二叉树也是如此分析的,因此我们可以总结出一个套路,就是遍历二叉树,然后找出节点的节点数和值总和,再算上自己的值减1(自己节点数为1)传递给父节点,并且取绝对值后加入到结果中.

完整代码+结果如下:

class Solution {
public:
    int res=0;
    int dfs(TreeNode* root){
        if(root==nullptr) return 0;
        int need=dfs(root->left)+dfs(root->right)+root->val-1;
        res+=abs(need);
        return need;
    }


    int distributeCoins(TreeNode* root) {
        dfs(root);
        return res;
    }
};

力扣每日一题2023.7.14在二叉树中分配硬币_第6张图片

你可能感兴趣的:(力扣每日一题,leetcode,算法,职场和发展)