Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • 数组

  • 链表

  • 字符串

  • 二叉树

    • 102.二叉树的层序遍历
    • 103.二叉树的锯齿形层序遍历
    • 124.二叉树中的最大路径和
    • 236.二叉树的最近公共祖先
    • 105.从前序与中序遍历序列构造二叉树
    • 662.二叉树最大宽度
    • 1080. 根到叶路径上的不足节点
    • 101. 对称二叉树
    • 226. 翻转二叉树
    • 114. 二叉树展开为链表
    • 1110. 删点成林
    • 337. 打家劫舍 III
    • 979. 在二叉树中分配硬币
      • 1.后序遍历
    • 222. 完全二叉树的节点个数
    • 513. 找树左下角的值
    • 968. 监控二叉树
    • 剑指offer34
    • 剑指 Offer 32 - III. 从上到下打印二叉树 III
    • 剑指 Offer 33. 二叉搜索树的后序遍历序列
    • 线索二叉树

    • 二叉搜索树

  • 动态规划

  • 深搜回溯

  • 数学贪心

  • 堆栈队列

  • 前缀和

  • 算法设计

  • 位运算

  • WA

  • 算法
  • 二叉树
phan
2023-07-14
目录

979. 在二叉树中分配硬币

# 979. 在二叉树中分配硬币 (opens new window)

# 1.后序遍历

单纯找到“富余”节点,然后找到空硬币节点,最后计算移动次数。这种做法完全做不出来,因为这其中还涉及到如何移动到“最近空硬币节点”的问题。

本题目的难点在于如何抽象搬运过程简化移动次数统计?

  • 遍历时,考虑当前节点需要取出的硬币个数。如果为负数则表示当前节点需要放入硬币。

  • dfs(root):返回以root节点作为根节点的子树总共需要“取出的硬币数量”。其中主要进行了两个操作:

    1. 统计移动次数:无论是放入还是取出一个节点,统计时都需要移动。Math.abs(dfs(root.left))表示左子树取出/放入的所有硬币放到当前root节点需要的步数。
    2. 盈亏抵消:左节点与右节点多出的与缺少的硬币数量,再加上root节点“贡献的”硬币数量,在root节点处进行加减正负抵消。

这样的做法之所以答案是正确的,原因在于:自底向上遍历+正负抵消法保证了当前资金流的流向是唯一的,因此当前统计的移动步数是最小的。

  • 这里唯一性指的是,假设Math.abs(dfs(root.right))>0

    • 如果左子树是取出(正流向),那么只能将所有多余的硬币放到父节点。统计的步数是将多的硬币从子节点放到父节点的步数。
    • 如果左子树是放入(负流向),那么只能将外面多余的金币放入左子树。统计的步数是将父节点多余硬币放入左子树的步数。

    因此资金流向总是流向父节点的。

  • 这里“最小”指的是全局步数最小。考虑一种情况【1,1,1,2,0,2,0】,可以证明,在优先满足子树再满足邻居的分配方案下,全局移动步数是最小的。

class Solution {
    int res=0;
    public int distributeCoins(TreeNode root) {
        dfs(root);
        return res;
    }
    public int dfs(TreeNode root){
        if(root==null) return 0;
        int l=dfs(root.left);
        int r=dfs(root.right);
        res+=Math.abs(l);
        res+=Math.abs(r);
        return l+r+(root.val-1);

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
编辑 (opens new window)
#Leetcode#二叉树
上次更新: 2023/12/15, 15:49:57
337. 打家劫舍 III
222. 完全二叉树的节点个数

← 337. 打家劫舍 III 222. 完全二叉树的节点个数→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式