并查集专题

初始化

            int[] fa = new int[n];
            //初始化,父节点为自身
            for (int i = 0; i < n; i++) {
                fa[i] = i;
            }

连接

我愿称为认父环节,一遍的是右边那个认左边那个做爹(看你喜欢)

操作是先找到各自的爹(如果没有就是自身),让右边的爹认左边的爹为爹,这样两个之间就有家族关系了

            for (List<Integer> pair : pairs) {
                int a = find(pair.get(0),fa);
                int b = find(pair.get(1),fa);
                fa[a] = find(b, fa);
            }

 最后推荐再检查一遍

如题2情况 假如3认1为爹后,如果3又和2认爹,最后运行只会让1的爹变成2,但是3的爹还是1

             for (int i = 0; i < n; i++) {
                fa[i]=find(fa[i]);
            }

c1202. 交换字符串中的元素 - 力扣(LeetCode)

    class Solution {
        public String smallestStringWithSwaps(String s, List<List<Integer>> pairs) {
            StringBuilder sb = new StringBuilder("");
            int n = s.length();
            int[] fa = new int[n];
            //初始化,父节点为自身
            for (int i = 0; i < n; i++) {
                fa[i] = i;
            }
            for (List<Integer> pair : pairs) {
                int a = find(pair.get(0),fa);
                int b = find(pair.get(1),fa);
                fa[a] = find(b, fa);
            }
            Map<Integer, PriorityQueue<Character>> queueMap = new HashMap<>();
            //重新找一遍 防止遗漏
            //
            for (int i = 0; i < n; i++) {
                fa[i] = find(i, fa);
                queueMap.computeIfAbsent(fa[i], k -> new PriorityQueue<>()).offer(s.charAt(i));
            }
            for (int i = 0; i < n; i++) {
                char c = queueMap.get(fa[i]).poll();
                sb.append(c);
            }
            return sb.toString();
        }
        //查找方法
        private int find(int i, int[] fa) {
            if (fa[i] != i) {
                fa[i] = find(fa[i], fa);
            }
            return fa[i];
        }
    }

839. 相似字符串组 - 力扣(LeetCode)

class Solution {
    public int numSimilarGroups(String[] strs) {
        int n=strs.length;
        int ans=0;
        Map<String,String> fa=new HashMap<>();
        for (int i = 0; i < n; i++) {
            fa.put(strs[i],strs[i]);
        }
        for (int i = 0; i < n; i++) {
            for (int j=i+1;j<n;j++){
                if(check(strs[i].toCharArray(),strs[j].toCharArray())){
                    String a=find(strs[i],fa);
                    String b=find(strs[j],fa);
                    fa.put(b,a);
                    System.out.println(i+" "+j);
                }
            }
        }
        for (int i = 0; i < n; i++) {
            find(strs[i],fa);
        }
        Set<String> set=new HashSet<>();
        for (String s:fa.values()){
            set.add(s);
        }
        return set.size();
    }
    String find(String a, Map<String,String> fa){
        if(!fa.get(a).equals(a)){
            fa.put(a,find(fa.get(a),fa));
        }
        return fa.get(a);
    }
    boolean check(char[] a,char[] b){

        int res=0;
        for (int i=0;i<a.length;i++){
            if(a[i]!=b[i])res++;
        }
        if(res!=2)return false;
        Arrays.sort(a);
        Arrays.sort(b);
        return java.lang.String.valueOf(a).equals(java.lang.String.valueOf(b));
    }
}

1579. 保证图可完全遍历 - 力扣(LeetCode)

class Solution {
    public int maxNumEdgesToRemove(int n, int[][] edges) {
        int[]fa1=new int[n+1];
        int[]fa2=new int[n+1];
        for (int i = 0; i < n+1; i++) {
            fa1[i]=i;
            fa2[i]=i;
        }
        Arrays.sort(edges,(o1, o2) -> o2[0]-o1[0]);
        int ans=0;
        for (int[] edge : edges) {
            int a=edge[1];
            int b=edge[2];
            if(edge[0]==1){
                a=find(a,fa1);
                b=find(b,fa1);
                if(a==b)
                {
                    ans++;
                    continue;
                }
                fa1[a]=b;
            }
            if(edge[0]==2){
                a=find(a,fa2);
                b=find(b,fa2);
                if(a==b)
                {
                    ans++;
                    continue;
                }
                fa2[a]=b;
            }
            if(edge[0]==3){
                int a1=find(a,fa1);
                int b1=find(b,fa1);
                int a2=find(a,fa2);
                int b2=find(b,fa2);
                if(a1==b1&&a2==b2){
                    ans++;
                    continue;
                }
                fa1[a1]=b1;fa2[a2]=b2;
            }
        }
        for (int i = 1; i < n + 1; i++) {
            if(find(fa1[1],fa1)!=find(fa1[i],fa1)||find(fa2[1],fa2)!=find(fa2[i],fa2))
                return -1;
        }
        return ans;
    }
    int find(int a,int[]fa){
        if(fa[a]!=a){
            fa[a]=find(fa[a],fa);
        }
        return fa[a];
    }
}

2503. 矩阵查询可获得的最大分数 - 力扣(LeetCode) 

    class Solution {
        public int[] maxPoints(int[][] grid, int[] queries) {
            int k = queries.length;
            int[] ans = new int[k];
            int n = grid.length;
            int m = grid[0].length;
            int[] fa = new int[100001];
            for (int i = 0; i <=100000; i++) {
                fa[i] = i;
            }
            int[] size = new int[100001];
            Arrays.fill(size, 1);
            PriorityQueue<int[]> queue = new PriorityQueue<>((o1, o2) -> o1[0] - o2[0]);
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (i != n - 1) {
                        queue.add(new int[]{Math.max(grid[i][j], grid[i + 1][j]), i * m + j, (i + 1) * m + j});
                    }
                    if (j != m - 1) {
                        queue.add(new int[]{Math.max(grid[i][j], grid[i][j + 1]), i * m + j, (i) * m + (j + 1)});
                    }
                }
            }
            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < k; i++) {
                map.put(queries[i], i);
            }
            int[][] queryIdx = new int[k][2];
            for (int i = 0; i < k; i++) {
                queryIdx[i][0] = queries[i];
                queryIdx[i][1] = i;
            }
            Arrays.sort(queryIdx, (o1, o2) -> o1[0] - o2[0]);
            for (int i = 0; i < k; i++) {
                while (!queue.isEmpty() && queue.peek()[0] < queryIdx[i][0]) {
                    int a = queue.peek()[1];
                    int b = queue.poll()[2];
                    a = find(a, fa);
                    b = find(b, fa);
                    if (a != b) {
                        fa[b] = a;
                        size[a] += size[b];
                    }
                }
                if (grid[0][0] < queryIdx[i][0]) {
                    ans[queryIdx[i][1]] = size[find(0,fa)];
                }
            }
            return ans;
        }

        int find(int a, int[] fa) {
            if (fa[a] != a) {
                fa[a] = find(fa[a], fa);
            }
            return fa[a];
        }
    }

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值