• 【LeetCode】按公因数计算最大组件大小 [H](并查集)


    952. 按公因数计算最大组件大小 - 力扣(LeetCode)

    一、题目

    给定一个由不同正整数的组成的非空数组 nums ,考虑下面的图:

    有 nums.length 个节点,按从 nums[0] 到 nums[nums.length - 1] 标记;
    只有当 nums[i] 和 nums[j] 共用一个大于 1 的公因数时,nums[i] 和 nums[j]之间才有一条边。
    返回 图中最大连通组件的大小 。

    示例 1:
     

    输入:nums = [4,6,15,35]
    输出:4
    

    示例 2:

    输入:nums = [20,50,9,63]
    输出:2

    示例 3:
     

    输入:nums = [2,3,6,7,4,12,21,39]
    输出:8
    

    提示:

    二、代码

    1. class Solution {
    2. public int largestComponentSize(int[] nums) {
    3. // 因子表, key 某个因子 value 哪个位置拥有这个因子
    4. HashMap factorMap = new HashMap<>();
    5. // 构建并查集,并查集中存储的数据是nums的下标
    6. UnionFind unionFind = new UnionFind(nums.length);
    7. // 去遍历nums数组,找到每一个数的所有因子
    8. for (int i = 0; i < nums.length; i++) {
    9. // 先单独算出来结果,不要写到for循环语句中,这样每一次循环都要算一遍,影响效率
    10. int limit = (int) Math.sqrt(nums[i]);
    11. // 找到num的所有因子,如果这个因子不曾被任何数拥有,就加入因子表,如果别的数也有这个因子,就说明这两个数是连通的,可以加入到同一个集合中,执行合并操作
    12. for (int k = 1; k <= limit; k++) {
    13. // nums[i] % k == 0,说明k是nums[i]的因子
    14. // 这种情况下k和nums[i]/k都是nums[i]的因子
    15. if (nums[i] % k == 0) {
    16. // 尽量减少声明和创建的语句
    17. int index;
    18. // 因为题目说公因子大于1才算连通,所以不将1因子加入到因子表
    19. if (k != 1) {
    20. // 如果因子表不存在k,就将k加入
    21. if (!factorMap.containsKey(k)) {
    22. // k被下标i拥有
    23. factorMap.put(k, i);
    24. // 如果已经有数拥有k因子了,就将这两个数合并
    25. } else {
    26. index = factorMap.get(k);
    27. unionFind.union(i, index);
    28. }
    29. }
    30. // 另一个因子是nums[i] / k
    31. int o = nums[i] / k;
    32. // 执行相同操作
    33. if (o != 1) {
    34. if (!factorMap.containsKey(o)) {
    35. factorMap.put(o, i);
    36. } else {
    37. index = factorMap.get(o);
    38. unionFind.union(i, index);
    39. }
    40. }
    41. }
    42. }
    43. }
    44. // 找到所有独立集合中大小最大的返回
    45. return unionFind.maxSize();
    46. }
    47. public static class UnionFind {
    48. public int[] parents;
    49. public int[] size;
    50. public int[] help;
    51. public UnionFind(int n) {
    52. parents = new int[n];
    53. size = new int[n];
    54. help = new int[n];
    55. // 初始化集合,O(N)
    56. for (int i = 0; i < n; i++) {
    57. parents[i] = i;
    58. size[i] = 1;
    59. }
    60. }
    61. public int find(int num) {
    62. int hi = 0;
    63. // 路径压缩
    64. while (parents[num] != num) {
    65. help[hi++] = num;
    66. num = parents[num];
    67. }
    68. for (int i = 0; i < hi; i++) {
    69. parents[help[i]] = num;
    70. }
    71. return num;
    72. }
    73. public void union(int num1, int num2) {
    74. int parent1 = find(num1);
    75. int parent2 = find(num2);
    76. if (parent1 != parent2) {
    77. int big = size[parent1] >= size[parent2] ? parent1 : parent2;
    78. int small = big == parent1 ? parent2 : parent1;
    79. parents[small] = big;
    80. size[big] += size[small];
    81. // 将samll集合大小设置为0,为maxSize方法做准备
    82. size[small] = 0;
    83. }
    84. }
    85. // 找到所有独立集合中大小最大的返回集合大小
    86. public int maxSize() {
    87. int max = 0;
    88. // 有效的代表节点对应的集合大小一定不是0,其他的位置就都是0
    89. for (int s : size) {
    90. max = Math.max(max, s);
    91. }
    92. return max;
    93. }
    94. }
    95. }

    三、解题思路 

    利用并查集来进行拥有非1公因子的数集合的合并,最后返回所有独立集合中大小最大的即可。

  • 相关阅读:
    洛谷千题详解 | P1014 [NOIP1999 普及组] Cantor 表【C++、Java语言】
    二进制转换16进制 快速心算
    Thingworx 8.*启动失败
    面了12家软件公司测试岗位,高频面试题大盘点,刷完谁都留不住我跳槽的心
    Echart 知识图谱--连接线段
    小程序-uni-app:将页面(html+css)生成图片/海报/名片,进行下载 保存到手机
    通过 Canal 将 MySQL 数据实时同步到 Easysearch
    解除百度安全验证
    macOS使用官方安装包安装python
    (王道考研计算机网络)第四章网络层-第五节3:BGP协议
  • 原文地址:https://blog.csdn.net/cy973071263/article/details/127980625