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比较)下能够收集到的最大硬币数量。通过位操作和递归,高效地遍历树并计算每个节点的贡献。

相关推荐
uesowys4 小时前
Apache Spark算法开发指导-Factorization machines classifier
人工智能·算法
季明洵5 小时前
C语言实现单链表
c语言·开发语言·数据结构·算法·链表
shandianchengzi5 小时前
【小白向】错位排列|图文解释公考常见题目错位排列的递推式Dn=(n-1)(Dn-2+Dn-1)推导方式
笔记·算法·公考·递推·排列·考公
I_LPL5 小时前
day26 代码随想录算法训练营 回溯专题5
算法·回溯·hot100·求职面试·n皇后·解数独
Yeats_Liao5 小时前
评估体系构建:基于自动化指标与人工打分的双重验证
运维·人工智能·深度学习·算法·机器学习·自动化
cpp_25015 小时前
P9586 「MXOI Round 2」游戏
数据结构·c++·算法·题解·洛谷
浅念-5 小时前
C语言编译与链接全流程:从源码到可执行程序的幕后之旅
c语言·开发语言·数据结构·经验分享·笔记·学习·算法
有时间要学习5 小时前
面试150——第五周
算法·深度优先
晚霞的不甘6 小时前
Flutter for OpenHarmony 可视化教学:A* 寻路算法的交互式演示
人工智能·算法·flutter·架构·开源·音视频
望舒5136 小时前
代码随想录day25,回溯算法part4
java·数据结构·算法·leetcode