强化二 Union Find

2018-12-17  本文已影响0人  谢谢水果

并查集: 一种用于支持集合快速合并和查找操作的数据结构
并查集能做的事情:

  1. 合并两个集合 O(1)
  2. 查询某个元素所在集合 O(1)
  3. 判断两个元素是否在同一个集合 O(1)
  4. 获得某个集合的元素个数 O(1) 同时定义一个count数组 维护count[root]=root集合元素数量
  5. 统计当前集合个数 O(1) 维护全局size 每成功合并(指把两个原来根不同元素合并到一起)一次 size--

注意:

连通性的问题都可以使用BFS和并查集
如果是在线数据 使用并查集
如果涉及把一个集合拆开的操作 使用BFS

题目列表:
lt589 Connecting Graph 判断两个点是不是在一个集合里
lt590 Connecting Graph II 获得某个集合中元素的个数
lt591 Connecting Graph III 获得集合总数
305 Number of Islands II 注意:把二维坐标转化成一位的 方便处理/这里是在线算法 使用并查集
261 Graph Valid Tree

lt1070 Accounts Merge BFS/并查集
先得到 email - namelist 对应map
然后namelist中元素个数大于一说明需要合并
最后统计结果
人作为并查集的节点 如果
todo:
lt1396 Set Union
lt477 Surrounded Regions
lt805 Maximum Association Set
128 Longest Consecutive Sequence

lt589 Connecting Graph 判断两个点是不是在一个集合里

public class ConnectingGraph {
   private int[] father;
   /*
   * @param n: An integer
   */public ConnectingGraph(int n) {
       // do intialization if necessary
       father = new int[n+1];
       for(int i=1; i<=n; i++){
           father[i] = i;
       }
   }

   /*
    * @param a: An integer
    * @param b: An integer
    * @return: nothing
    */
   public void connect(int a, int b) {
       // write your code here
       int rootA = find(a);
       int rootB = find(b);
       if(rootA != rootB){
           father[rootA] = rootB;
       }
   }

   /*
    * @param a: An integer
    * @param b: An integer
    * @return: A boolean
    */
   public boolean query(int a, int b) {
       // write your code here
       int rootA = find(a);
       int rootB = find(b);
       if(rootA != rootB)
           return false;
       return true;
   }
   public int find(int a) {
       return nonrecursiveFind(a);
   }
   public int recursiveFind(int a) {
       // write your code here
       if(father[a] == a)
           return a;
       father[a] = recursiveFind(father[a]);
       return father[a];
   }
   public int nonrecursiveFind(int a) {
       // write your code here
       if(father[a] == a)
           return a;
       List<Integer> nodes = new ArrayList<>();
       while(father[a]!=a){
           nodes.add(a);
           a = father[a];
       }
       for(Integer node : nodes){
           father[node] = a;
       }
       return a;
   }
}

lt590 Connecting Graph II 获得某个集合中元素的个数

public class ConnectingGraph2 {
   int[] father;
   int[] count;
   /*
   * @param n: An integer
   */public ConnectingGraph2(int n) {
       // do intialization if necessary
       father = new int[n+1];
       count = new int[n+1];
       for(int i=1; i<=n; i++){
           count[i] = 1;
           father[i] = i;
       }
   }

   /*
    * @param a: An integer
    * @param b: An integer
    * @return: nothing
    */
   public void connect(int a, int b) {
       // write your code here
       int rootA = find(a);
       int rootB = find(b);
       if(rootA!=rootB){
           father[rootA] = rootB;
           count[rootB] = count[rootA] + count[rootB];
       }
   }

   /*
    * @param a: An integer
    * @return: An integer
    */
   public int query(int a) {
       // write your code here
       int root = find(a);
       return count[root];
   }
   
   public int find (int a){
       if(father[a]==a)
           return a;
       father[a] = find(father[a]);
       return father[a];
   }
}

lt591 Connecting Graph III 获得集合总数

public class ConnectingGraph3 {
   int[] father;
   int count;
   /*
   * @param n: An integer
   */public ConnectingGraph3(int n) {
       // do intialization if necessary
       father = new int[n+1];
       count = n;
       for(int i=1; i<=n; i++){
           father[i] = i;
       }
   }
   /**
    * @param a: An integer
    * @param b: An integer
    * @return: nothing
    */
   public void connect(int a, int b) {
       // write your code here
       int rootA = find(a);
       int rootB = find(b);
       if(rootA!=rootB){
           father[rootA] = rootB;
           count--;
       }
   }

   /**
    * @return: An integer
    */
   public int query() {
       // write your code here
       return count;
   }
   
   private int find(int a){
       if(father[a] == a) 
           return a;
       father[a] = find(father[a]);
       return father[a];
   }
   
}

305 Number of Islands II

class Solution {
   int[] father;
   int count;
   public List<Integer> numIslands2(int m, int n, int[][] positions) {
       List<Integer> results = new ArrayList<>();
       if(positions==null || positions.length==0 || positions[0]==null || positions[0].length==0)
           return results;
       father = new int[m*n];
       for(int i=0; i<m*n; i++)
           father[i] = -1;
       int[] dirx = {1, -1, 0, 0};
       int[] diry = {0, 0, 1, -1};
       for(int[] position: positions){
           count++;
           int x = position[0];
           int y = position[1];
           int index = x*n+y;
           father[index] = index;
           for(int k=0; k<4; k++){
               int newx = x+dirx[k];
               int newy = y+diry[k];
               if(isValid(newx, newy, m, n)){
                   connect(index, newx*n+newy);
               }
           }
           results.add(count);
       }
       return results;
   }
   
   private boolean isValid(int x, int y, int m, int n){
       return x>=0 && x<m && y>=0 && y<n &&  father[x*n+y]!=-1;
   }
   private int find(int a){
       if(father[a] == a)
           return a;
       father[a] = find(father[a]);
       return father[a];
   }
   private void connect(int a, int b){
       int fathera = find(a);
       int fatherb = find(b);
       if(fathera==fatherb)
           return;
       father[fathera] = fatherb;
       count--;
   }
}

261 Graph Valid Tree

class Solution {
   public boolean validTree(int n, int[][] edges) {
       // return bfs(n, edges);
       return unionFind(n, edges);
   }
   private boolean unionFind(int n, int[][] edges){
       if(edges.length!=n-1)
           return false;
       int count = n;
       int[] father = new int[n];
       for(int i=0; i<n; i++){
           father[i] = i;
       }
       for(int[] edge: edges){
           count = union(edge[0], edge[1], count, father);
       }
       return count==1;
   }
   private int find(int a, int[] father){
       if(a==father[a])
           return a;
       father[a] = find(father[a], father);
       return father[a];
   }
   private int union(int a, int b, int count, int[] father){
       int fathera = find(a, father);
       int fatherb = find(b, father);
       if(fathera == fatherb)
           return count;
       father[fathera] = father[b];
       count--;
       return count;
   }
   
   
   
   private boolean bfs(int n, int[][] edges){
       if(edges.length!=n-1)
           return false;
       Map<Integer, Set<Integer>> graph = new HashMap<>();
       for(int[] edge : edges){
           int n0 = edge[0];
           int n1 = edge[1];
           Set<Integer> set0 = graph.getOrDefault(n0, new HashSet<>());
           Set<Integer> set1 = graph.getOrDefault(n1, new HashSet<>());
           set0.add(n1);
           set1.add(n0);
           graph.put(n0, set0);
           graph.put(n1, set1);
       }
       Queue<Integer> queue = new LinkedList<>();
       Set<Integer> visited = new HashSet<>();
       queue.offer(0);
       visited.add(0);
       int count = 0;
       while(!queue.isEmpty()){
           int current = queue.poll();
           count++;
           for(Integer next : graph.getOrDefault(current, new HashSet<>())){
               if(visited.contains(next))
                   return false;
               visited.add(next);
               Set<Integer> set = graph.get(next);
               set.remove(current);
               graph.put(next, set);
               queue.offer(next);
           }
       }
       System.out.println(count);
       return count == n;
   }
}

1070 Accounts Merge

public class Solution {
   /**
    * @param accounts: List[List[str]]
    * @return: return a List[List[str]]
    */
   int[] father;
   public List<List<String>> accountsMerge(List<List<String>> accounts) {
       // write your code here
       List<List<String>> results = new ArrayList<>();
       father = new int[accounts.size()];
       for(int i=0; i<father.length; i++){
           father[i] = i;
       }
       Map<String, List<Integer>> email2Name = getEmail2Name(accounts);
       for(String email : email2Name.keySet()){
           List<Integer> idList = email2Name.get(email);
           for(int i=1; i<idList.size(); i++){
               union(idList.get(i), idList.get(0));
           }
       }
       for(int i: father){
           System.out.println(father[i]);
       }
       Map<Integer, Set<String>> id2email = merge(accounts);
       System.out.println(id2email.size());
       Set<String> test = id2email.get(0);
       helper(results, id2email, accounts);
       return results;
   }
   private void helper(List<List<String>> results, Map<Integer, Set<String>> id2email, List<List<String>> accounts){
       for(Integer id: id2email.keySet()){
           List<String> result = new ArrayList<>();
           for(String email : id2email.get(id)){
               result.add(email);
           }
           Collections.sort(result);
           String name = accounts.get(id).get(0);
           result.add(0, name);
           results.add(result);
       }
   }
   private Map<Integer, Set<String>> merge(List<List<String>> accounts){
       Map<Integer, Set<String>> result = new HashMap<>();
       for(int i=0; i<father.length; i++){
           Set<String> emailSet = result.getOrDefault(find(i), new HashSet<>());
           for(int j=1; j<accounts.get(i).size(); j++){
               emailSet.add(accounts.get(i).get(j));
           }
           result.put(find(i), emailSet);

       }
       return result;
   }
   private Map<String, List<Integer>> getEmail2Name(List<List<String>> accounts){
       Map<String, List<Integer>> result = new HashMap<>();
       for(int id=0; id<accounts.size(); id++){
           List<String> emailList = accounts.get(id);
           for(int i=1; i<emailList.size(); i++){
               String email = emailList.get(i);
               List<Integer> idList = result.getOrDefault(email, new ArrayList<Integer>());
               idList.add(id);
               result.put(email, idList);
           }
       }
       return result;
   }
   private void union(int a, int b){
       int fatherA = find(a);
       int fatherB = find(b);
       if(fatherA!=fatherB){
          father[fatherA] = fatherB; 
       }
   }
   private int find(int a){
       if(a == father[a])
           return a;
       father[a] = find(father[a]);
       return father[a];
   }
   
}
上一篇下一篇

猜你喜欢

热点阅读