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

相关推荐
点我头像干啥7 分钟前
机器学习中的聚类分析算法:原理与应用
人工智能·算法·机器学习
仟濹13 分钟前
【C/C++】双指针与前缀和
c语言·c++·算法
www_pp_21 分钟前
# 决策树与PCA降维在电信客户流失预测中的应用
算法·决策树·机器学习
Tony8834 分钟前
快速选择算法的时间复杂度分析
算法
zccccc_1 小时前
Funrec读书笔记5️⃣:序列以及多任务排序模型(包含DIN,MIEN,待更新:MMOE,PLE)
算法
ccLianLian1 小时前
算法·回溯
算法·深度优先
jieyucx1 小时前
深入剖析C语言中的指针与数组
java·c语言·算法
阿巴~阿巴~1 小时前
二分 —— 基本算法刷题路程
数据结构·c++·算法
前端 贾公子1 小时前
力扣1338 === 贪心算法解决数组减半问题
算法·leetcode·贪心算法
HelloDam2 小时前
leetcode28.找出字符串中第一个匹配项的下标,KMP算法保姆级教程(带动图)
java·后端·算法