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

相关推荐
计算机小白一个6 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
万事可爱^6 小时前
HDBSCAN:密度自适应的层次聚类算法解析与实践
算法·机器学习·数据挖掘·聚类·hdbscan
大数据追光猿8 小时前
Python应用算法之贪心算法理解和实践
大数据·开发语言·人工智能·python·深度学习·算法·贪心算法
Dream it possible!9 小时前
LeetCode 热题 100_在排序数组中查找元素的第一个和最后一个位置(65_34_中等_C++)(二分查找)(一次二分查找+挨个搜索;两次二分查找)
c++·算法·leetcode
夏末秋也凉9 小时前
力扣-回溯-46 全排列
数据结构·算法·leetcode
南宫生9 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
柠石榴9 小时前
【练习】【回溯No.1】力扣 77. 组合
c++·算法·leetcode·回溯
Leuanghing9 小时前
【Leetcode】11. 盛最多水的容器
python·算法·leetcode
qy发大财9 小时前
加油站(力扣134)
算法·leetcode·职场和发展
王老师青少年编程9 小时前
【GESP C++八级考试考点详细解读】
数据结构·c++·算法·gesp·csp·信奥赛