Leecode刷题C语言之收集所有金币可获得的最大积分

执行结果:通过

执行用时和内存消耗如下:

复制代码
int dfs(int node, int parent, int f, int* coins, int k, int **children, int *childCount, int **memo) {
    if (memo[node][f] != -1) {
        return memo[node][f];
    }
    int res0 = (coins[node] >> f) - k;
    int res1 = coins[node] >> (f + 1);
    for (int i = 0; i < childCount[node]; ++i) {
        int child = children[node][i];
        if (child == parent) {
            continue;
        }
        res0 += dfs(child, node, f, coins, k, children, childCount, memo);
        if (f + 1 < 14) {
            res1 += dfs(child, node, f + 1, coins, k, children, childCount, memo);
        }
    }
    return memo[node][f] = fmax(res0, res1);
}

int maximumPoints(int **edges, int edgesSize, int *edgesColSize, int *coins, int coinsSize, int k) {
    int* childCount = (int*)malloc(coinsSize * sizeof(int));
    memset(childCount, 0, coinsSize * sizeof(int));
    for (int i = 0; i < edgesSize; ++i) {
        int u = edges[i][0];
        int v = edges[i][1];
        childCount[u]++;
        childCount[v]++;
    }

    int** children = (int**)malloc(coinsSize * sizeof(int*));
    for (int i = 0; i < coinsSize; ++i) {
        children[i] = (int*)malloc(childCount[i] * sizeof(int));
    }
    memset(childCount, 0, coinsSize * sizeof(int));
    for (int i = 0; i < edgesSize; ++i) {
        int u = edges[i][0];
        int v = edges[i][1];
        children[u][childCount[u]++] = v;
        children[v][childCount[v]++] = u;
    }

    int **memo = (int **)malloc(coinsSize * sizeof(int *));
    for (int i = 0; i < coinsSize; i++) {
        memo[i] = (int *)malloc(14 * sizeof(int));
        memset(memo[i], -1, 14 * sizeof(int));
    }
    int result = dfs(0, -1, 0, coins, k, children, childCount, memo);
    for (int i = 0; i < coinsSize; ++i) {
        free(children[i]);
        free(memo[i]);
    }
    free(children);
    free(memo);
    free(childCount);
    return result;
}

解题思路

这段代码实现了一个深度优先搜索(DFS)算法,用于解决一个特定的问题,该问题涉及到一个树状结构,每个节点都拥有一定数量的"硬币"(由coins数组表示),并且有一个特定的参数k。目标是在满足某些条件下,最大化能够收集到的硬币数量。以下是对代码思路的详细解释:

函数 dfs

  • 参数解释
    • node:当前正在访问的节点。
    • parent:当前节点的父节点,用于避免向上回溯时重复访问父节点,形成环路。
    • f:当前考虑的位(bit),用于在coins数组中按位选择硬币数量。
    • coins:一个整数数组,每个元素表示对应节点的硬币数量,通过位操作来访问不同范围内的硬币数量。
    • k:一个阈值,用于与按位操作后的硬币数量进行比较。
    • children:一个二维数组,存储每个节点的子节点列表。
    • childCount:一个整数数组,存储每个节点的子节点数量。
    • memo:一个二维数组,用于记忆化搜索,避免重复计算。
  • 逻辑
    1. 记忆化检查 :首先检查memo[node][f]是否已经被计算过,如果是,则直接返回结果。
    2. 计算当前节点的贡献
      • res0:当前节点在不考虑更高位的情况下,能够贡献的硬币数量(与k比较后)。
      • res1:当前节点在考虑更高位的情况下,能够贡献的硬币数量。
    3. 递归遍历子节点
      • 对于每个子节点,递归调用dfs函数,更新res0res1
      • 注意,当考虑更高位时(f + 1),只有f + 1 < 14时才进行递归,这可能是因为coins数组中的数值最多只有14位有效(或出于其他特定限制)。
    4. 返回结果 :返回fmax(res0, res1),即两种情况下的最大值,并更新memo[node][f]

函数 maximumPoints

  • 参数解释
    • edges:一个二维数组,表示树的边,edges[i] = [u, v]表示节点u和节点v之间有一条边。
    • edgesSizeedges数组的大小。
    • edgesColSizeedges数组中每个子数组的大小(这里似乎未直接使用,但通常用于表示二维数组的第二维大小)。
    • coins:一个整数数组,表示每个节点的硬币数量。
    • coinsSizecoins数组的大小,也即节点的数量。
    • k:与dfs函数中的k相同,用于比较硬币数量。
  • 逻辑
    1. 初始化 :为childCountchildrenmemo数组分配内存,并初始化。
    2. 构建树的表示 :通过遍历edges数组,构建每个节点的子节点列表和子节点数量。
    3. 记忆化搜索 :调用dfs函数,从根节点(假设为0)开始搜索,parent参数设为-1表示根节点没有父节点。
    4. 释放内存:释放之前分配的内存,避免内存泄漏。
    5. 返回结果 :返回dfs函数的结果,即从根节点开始能够收集到的最大硬币数量。

总结

这段代码通过深度优先搜索(DFS)和记忆化搜索,在给定一个树状结构和每个节点的硬币数量的情况下,计算并返回在满足特定条件(与k比较)下能够收集到的最大硬币数量。通过位操作和递归,高效地遍历树并计算每个节点的贡献。

相关推荐
YuanDaima20482 分钟前
二分查找基础原理与题目说明
开发语言·数据结构·人工智能·笔记·python·算法
阿Y加油吧8 分钟前
两道中等 DP 题拆解:打家劫舍 & 完全平方数
算法·leetcode·动态规划
七颗糖很甜11 分钟前
python实现全国雷达拼图数据的SCIT风暴识别
python·算法·scipy
B325帅猫-量子前沿技术研究所1 小时前
PSD和FFT的关系
人工智能·算法
闻缺陷则喜何志丹1 小时前
【排序】P6149 [USACO20FEB] Triangles S|普及+
c++·算法·排序·洛谷
avocado_green2 小时前
【LeetCode】90. 子集 II
算法·leetcode
tankeven2 小时前
HJ178 【模板】双指针
c++·算法
君义_noip2 小时前
信息学奥赛一本通 4131:【GESP2506六级】学习小组 | 洛谷 P13015 [GESP202506 六级] 学习小组
算法·动态规划·gesp·信息学奥赛
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 72. 编辑距离 | C++ 经典 DP 增删改状态转移
c++·算法·leetcode
穿条秋裤到处跑2 小时前
每日一道leetcode(2026.04.16):距离最小相等元素查询
算法·leetcode·职场和发展