• LeetCode·每日一题·952.按公因数计算最大组件大小·并查集


    题目

     

    示例

     

    思路

    思路:
    通过元素间的公因数将彼此连接起来。

    1.并查集:

    构建时无需按集合大小进行合并,可直接合并。最大的连通组件 可通过对并查集一次遍历求得。
    配合路径压缩。见find函数。
    2.公因数:

    注意循环中 i * i <= num, 如果数据范围更大的话,可能会溢出。 用 i <= num / i 更好。


    举例例如:
    nums = [4 , 6 , 12, 15]
    其中nums中 每个数num 的大于2的因数为:
    4  ->  2
    6  ->  2, 3
    12 ->  2, 3, 4, 6
    15 ->  3, 5
    建立并查集时,通过 因数 2 可将 4, 6, 12连通。
    通过 因数3 可将 6, 12, 15 连通。
    而因数 2 和因数 3 也是连通的(如2 是3 的父节点)。
    则 原数组中的 四个数连通。其在并查集中 具有相同的父节点。

    求解
    最后对数组一次遍历,若其父节点相同,则在同一个连通组件中。
    更新每个父节点出现的最大次数即可。

    代码

    1. #define MAX(a, b) ((a) > (b) ? (a) : (b))
    2. typedef struct UnionFind {
    3. int *parent;
    4. int *rank;
    5. } UnionFind;
    6. UnionFind* unionFindCreate(int n) {
    7. UnionFind *obj = (UnionFind *)malloc(sizeof(UnionFind));
    8. obj->parent = (int *)malloc(sizeof(int) * n);
    9. obj->rank = (int *)malloc(sizeof(int) * n);
    10. memset(obj->rank, 0, sizeof(int) * n);
    11. for (int i = 0; i < n; i++) {
    12. obj->parent[i] = i;
    13. }
    14. return obj;
    15. }
    16. int find(const UnionFind *obj, int x) {
    17. if (obj->parent[x] != x) {
    18. obj->parent[x] = find(obj, obj->parent[x]);
    19. }
    20. return obj->parent[x];
    21. }
    22. void uni(UnionFind *obj, int x, int y) {
    23. int rootx = find(obj, x);
    24. int rooty = find(obj, y);
    25. if (rootx != rooty) {
    26. if (obj->rank[rootx] > obj->rank[rooty]) {
    27. obj->parent[rooty] = rootx;
    28. } else if (obj->rank[rootx] < obj->rank[rooty]) {
    29. obj->parent[rootx] = rooty;
    30. } else {
    31. obj->parent[rooty] = rootx;
    32. obj->rank[rootx]++;
    33. }
    34. }
    35. }
    36. void unionFindFree(UnionFind *obj) {
    37. free(obj->parent);
    38. free(obj->rank);
    39. free(obj);
    40. }
    41. int largestComponentSize(int* nums, int numsSize) {
    42. int m = nums[0];
    43. for (int i = 0; i < numsSize; i++) {
    44. m = MAX(m, nums[i]);
    45. }
    46. UnionFind *uf = unionFindCreate(m + 1);
    47. for (int i = 0; i < numsSize; i++) {
    48. int num = nums[i];
    49. for (int i = 2; i * i <= num; i++) {
    50. if (num % i == 0) {
    51. uni(uf, num, i);
    52. uni(uf, num, num / i);
    53. }
    54. }
    55. }
    56. int *counts = (int *)malloc(sizeof(int) * (m + 1));
    57. memset(counts, 0, sizeof(int) * (m + 1));
    58. int ans = 0;
    59. for (int i = 0; i < numsSize; i++) {
    60. int root = find(uf, nums[i]);
    61. counts[root]++;
    62. ans = MAX(ans, counts[root]);
    63. }
    64. free(counts);
    65. unionFindFree(uf);
    66. return ans;
    67. }

    时间空间复杂度

  • 相关阅读:
    系统整理K8S的配置管理实战-建议收藏系列
    学习学习之高效学习
    LayUi之用户(URUD)
    UE4 材质学习 (02-利用UV来调整纹理)
    邮件钓鱼的防守策略
    【Vue3】3-6 : 仿ElementPlus框架的el-button按钮组件实
    Python自动化办公(一) —— 根据PDF文件批量创建Word文档
    “在 ArchiMate EA 建模中的组合关系:构建块和依赖关系
    Pytorch C++ 前端第二部分:输入、权重和偏差
    LUCEDA IPKISS------Definition Properties 表格查询
  • 原文地址:https://blog.csdn.net/m0_64560763/article/details/126072886