【算法心得】硬币通过二叉树传递的题,分治精髓是干自己的事

https://leetcode.cn/problems/distribute-coins-in-binary-tree/

这个题刚开始的思路是对树进行一个中序遍历,像有一个铲子从左往右推,所过之处摞起来的金币堆都被铲平,多出来的金币落到右边的金币坑里(或左边的金币坑)

但是这样有一个问题,怎么知道多余的金币是从哪个位置来的呢,那岂不是每个金币都要存它是谁多出来的,然后再算从当前位置到原始位置的距离,太繁琐了


既然这样不行,考虑分治,每一个子树都相当于进行了一个调度,把左边多出来的放到右边,右边多出来的放到左边

这个过程金币不一定够,父亲还得向上借。不过这个不用担心,先假装借到了,因为肯定够

父亲要借的金币数刚好也是爷爷所要知道的调度的信息,就以这个作为dfs传递的值吧


但是写着写着发现,光有这个量还不够,我们要最终求的是调度的步数,光是传递金币的量不行,还要传递步数

对于一个子树,要做的有三个步骤:左孩子平衡好自身,有孩子平衡好自身,向上借/供奉金币

向上借/供奉金币所做的步数,正好就是刚才的那个金币数
平衡好自身需要的步骤数=左孩子平衡步骤数+右孩子平衡步骤数+向上借/供奉金币数

因此,步骤数也应作为dfs传递的量


看了题解,有人是后序遍历(仔细想想,我这个虽然函数名写的dfs,也应该归到后序遍历上,因为虽然搜索的过程是根左右,但是处理的顺序是左右根,先搜到了根,但是等左右处理好了才根据它们的值再处理根),然后她也递归,但是只传一个值

    private int ans = 0;
    public int lrd(TreeNode root){
        root.val += lrd(root.left);
        root.val += lrd(root.right);
        ans += Math.abs(root.val - 1);
        return root.val - 1;
    }

她直接把.val给改了,相当于改成了我那里的借/多的金币,这样就不用传了

步数那块,她没有管左边平衡自己要多少步,右孩子平衡自身要多少步,它只关心一个数据,那就是要向上借/送多少个金币。这是自己比孩子多做的事

而孩子要多少步,孩子自己会直接告诉全局变量ans的。反正每个节点都只处理一次,不重不漏的

这样挺好,这才是真正的分治,管好自己,管孩子干啥

你可能感兴趣的:(算法)