package UnionFind;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;public class UnionFindProblem {public static void main(String[] args) {// TODO Auto-generated method stub
}/** 网上查了一下:http://blog.csdn.net/dm_vincent/article/details/7655764* 这个人写的不错,但是他是抄袭这个普林斯顿的教授的视频:* https://www.youtube.com/watch?v=H0bkmI1Xsxg&list=PLe-ggMe31CTexoNYnMhbHaWhQ0dvcy43t&index=2#t=379.668* Union Find主要有两个部分,一个部分是Find Query,Check if two objects are in the same component.* 另一个部分是Union Command,也就是replace components containing two objects with their union.* 那么我们构建一个UF class* public class UF* UF(int N)------initialize with N object* void union(int p,int q)--------add connection between p and q* boolean connected(int p,int q)-------are p and q in the same component?* 那么如何来构建Data Structure呢?* Integer array id[] of size N and p and q are connected iff they have the same id.*       0 1  2 3  4  5 6 7 8* id[]  0 1  1 8  8  0 0 1 8 8表明0,5,6相连的* 那么Find就只需要看id相不相等,然后Union就相对来说比较复杂* To Merge components containing p and q, change all entries whose id equals id[p] to id[q].* id[]  1 1 1 8 8 1 1 1 8 8       after union of 6 and 1*/public class QuickFindUF{private int[] id;public QuickFindUF(int N){id=new int[N];for(int i=0;i<N;i++)id[i]=i;}public boolean connected(int p,int q){return id[p]==id[q];}public void union(int p,int q){int pid=id[p];int qid=id[q];for(int i=0;i<id.length;i++)if(id[i]==pid)id[i]=qid;}/** 那么我们能不能再把程序更进步一下吗?Quick-Union还是一样的ds,但是,这里id[i] is parent of i,* Root of i is id[id[id[..id[i]..]]].Keep going until it doesn't change*     0 1 2 3 4 5 6 7 8 9* id[]0 1 9 4 9 6 6 7 8 9* 0   1    9     6   7   8*         / \    |*         2 4    5*           |*           3* 这里9,2,4,3在一起* check if p and q have the same root* Union to merge components containing p and q, set the id of p's root to the id of q's root*/public class QuickUnionUF2{private int[] id;public QuickUnionUF2(int N){id=new int[N];for(int i=0;i<N;i++)id[i]=i;}private int root(int i){while(i!=id[i])i=id[i];//一直找到最高的父节点return i;}public boolean connected(int p,int q){return root(p)==root(q);}public void union(int p,int q){int i=root(p);int j=root(q);id[i]=j;}}}/** 上面两种的比较,*           initialize    union    find    defect* quick-find    N          N        1      Union too expensive* quick-union   N          N        N      Find too expensive,tree are too tall* weightd QU    N         lgN      lgN* 我们会发现如果用quick union的话树会非常的长,所以我们不能固定模式的union(a,b)一定是把b加到a的子树,我们* 应该看ab树的大小,把小的放在大的下面,这样可以节省一部分查找时间*/
//
    /** 130. Surrounded Regions* 2016-4-3 by Mingyang* union 什么:所有从边界可达的O元素union在一起* union 目的:union完成后那些没有在边界可达O集合中的O是需要翻转的*/public void solve(char[][] board) {if (board == null || board.length == 0 || board[0].length == 0)return;int rows = board.length, cols = board[0].length;int oRoot = rows * cols;initUnionFind(rows * cols);for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {if (board[i][j] == 'X') continue;int curr = i * cols + j;if (i == 0 || i == rows - 1 || j == 0 || j == cols - 1) {union(curr, oRoot);} else {if (j + 1 < cols && board[i][j + 1] == 'O')union(curr, i * cols + j + 1);if (j - 1 >= 0 && board[i][j - 1] == 'O')union(curr, i * cols + j - 1);if (i + 1 < rows && board[i + 1][j] == 'O')union(curr, (i + 1) * cols + j);if (i - 1 >= 0 && board[i - 1][j] == 'O')union(curr, (i - 1) * cols + j);}}}for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {if (board[i][j] == 'O' && find(i * cols + j) != oRoot) {board[i][j] = 'X';}}}}int[] s;int[] rank;private void initUnionFind(int n) {s = new int[n + 1];rank = new int[n + 1];for (int i = 0; i <= n; i++)s[i] = i;rank[n] = n + 1;}private int find(int p) {if (s[p] == p) return p;else return s[p] = find(s[p]);}private void union(int p, int q) {int pRoot = find(p), qRoot = find(q);if (pRoot == qRoot) return;if (rank[pRoot] < rank[qRoot]) {//保证小的树在大的下面s[pRoot] = qRoot;} else {if (rank[pRoot] == rank[qRoot])rank[pRoot]++;s[qRoot] = pRoot;}}/** 200.Number of Islands * 2016-4-3 by Mingyang* union 什么:两个相邻的1元素* union 目的:union后计数union集合数量(通过计数union数组中根节点数量)*/class UF {public int count = 0;public int[] id = null;public UF(int m, int n, char[][] grid) {for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {if(grid[i][j] == '1') count++;}}id = new int[m * n];for(int i = 0; i < m * n; i++) {id[i] = i;}}public int find(int p) {while(p != id[p]) {id[p] = id[id[p]];p = id[p];}return p;}public boolean isConnected(int p, int q) {int pRoot = find(p);int qRoot = find(q);if(pRoot != qRoot) return false;else return true;}public void union(int p, int q) {int pRoot = find(p);int qRoot = find(q);if(pRoot == qRoot) return;id[pRoot] = qRoot;count--;}}public int numIslands(char[][] grid) {if(grid.length == 0 || grid[0].length == 0) return 0;int m = grid.length, n = grid[0].length;UF uf = new UF(m , n, grid);for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {if(grid[i][j] == '0') continue;int p = i * n + j;int q;if(i > 0 && grid[i - 1][j] == '1') {q = p - n;uf.union(p, q);}if(i < m - 1 && grid[i + 1][j] == '1') {q = p + n;uf.union(p, q);}if(j > 0 && grid[i][j - 1] == '1') {q = p - 1;uf.union(p, q);}if(j < n - 1 && grid[i][j + 1] == '1') {q = p + 1;uf.union(p, q);}}}return uf.count;}//当然你也会觉得下面的可能更简单,那就是另外一种情况了,//设一个叫count的值,没遇到一个1,就把所有相连的1全部变为0,这样,到底遇到几次1,就是最终有几个小岛啦public int numIslands2(char[][] grid) {if (grid == null || grid.length == 0 || grid[0].length == 0)return 0;int count = 0;for (int i = 0; i < grid.length; i++) {for (int j = 0; j < grid[0].length; j++) {if (grid[i][j] == '1') {count++;dfs(grid, i, j);}}}return count;}public void dfs(char[][] grid, int i, int j) {// validity checkingif (i < 0 || j < 0 || i > grid.length - 1 || j > grid[0].length - 1)return;// if current cell is water or visitedif (grid[i][j] != '1')return;// set visited cell to '0'grid[i][j] = '0';// merge all adjacent landdfs(grid, i - 1, j);dfs(grid, i + 1, j);dfs(grid, i, j - 1);dfs(grid, i, j + 1);}/** 261.Graph Valid Tree* 2016-4-3 by Mingyang* 我们在Graph里面用其他方法做了一下这里我们再用并查集来做* union 什么:一条边的两个顶点* union 目的:若union两个顶点时发现根一样,说明已经在同一棵树中,* 说明输入graph存在环,非tree;union结束后,计数有多少个不同的根,当且仅当存在一个根时事vaild tree*/    public boolean validTree(int n, int[][] edges) {UnionFind uf = new UnionFind(n);for(int i = 0; i < edges.length; i++){// 如果两个节点已经在同一集合中,说明新的边将产生环路if(!uf.union(edges[i][0], edges[i][1])){return false;}}return uf.count() == 1;}   public class UnionFind {      int[] ids;int cnt;    public UnionFind(int size){this.ids = new int[size];//初始化并查集,每个节点对应自己的集合号for(int i = 0; i < this.ids.length; i++){this.ids[i] = i;}this.cnt = size;}public boolean union(int m, int n){int src = find(m);int dst = find(n);//如果两个节点不在同一集合中,将两个集合合并为一个if(src != dst){for(int i = 0; i < ids.length; i++){if(ids[i] == src){ids[i] = dst;}}// 合并完集合后,集合数减一cnt--;return true;} else {return false;}}public int find(int m){return ids[m];}public int count(){return cnt;}}/** 305    Number of Islands II* 2016-4-3 by Mingyang* Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k ). * Originally, the 2D matrix is all 0 which means there is only sea in the matrix. * The list pair has k operator and each operator has two integer A[i].x, A[i].y means * that you can change the grid matrix[A[i].x][A[i].y] from sea to island. * Return how many island are there in the matrix after each operator.*/private int[][] dir = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};public List<Integer> numIslands2(int m, int n, int[][] positions) {UnionFind2D islands = new UnionFind2D(m, n);List<Integer> ans = new ArrayList<Integer>();for (int[] position : positions) {int x = position[0], y = position[1];int p = islands.add(x, y);for (int[] d : dir) {int q = islands.getID(x + d[0], y + d[1]);if (q > 0 && !islands.find(p, q))islands.unite(p, q);}ans.add(islands.size());}return ans;}
}
class UnionFind2D {private int[] id;private int[] sz;private int m, n, count;public UnionFind2D(int m, int n) {this.count = 0;this.n = n;this.m = m;this.id = new int[m * n + 1];this.sz = new int[m * n + 1];}public int index(int x, int y) { return x * n + y + 1; }public int size() { return this.count; }public int getID(int x, int y) {if (0 <= x && x < m && 0<= y && y < n)return id[index(x, y)];return 0;}public int add(int x, int y) {int i = index(x, y);id[i] = i; sz[i] = 1;++count;return i;}public boolean find(int p, int q) {return root(p) == root(q);}public void unite(int p, int q) {int i = root(p), j = root(q);if (sz[i] < sz[j]) { //weighted quick unionid[i] = j; sz[j] += sz[i];} else {id[j] = i; sz[i] += sz[j];}--count;}private int root(int i) {for (;i != id[i]; i = id[i])id[i] = id[id[i]]; //path compressionreturn i;}
}

转载于:https://www.cnblogs.com/zmyvszk/p/5351494.html

Leetcode总结之Union Find相关推荐

  1. LeetCode MySQL 1205. 每月交易II(union all)*

    文章目录 1. 题目 2. 解题 1. 题目 Transactions 记录表 +----------------+---------+ | Column Name | Type | +------- ...

  2. LeetCode MySQL 602. 好友申请 II :谁有最多的好友(union all)

    文章目录 1. 题目 2. 解题 1. 题目 在 Facebook 或者 Twitter 这样的社交应用中,人们经常会发好友申请也会收到其他人的好友申请. 表 request_accepted 存储了 ...

  3. LeetCode MySQL 1264. 页面推荐(union)

    文章目录 1. 题目 2. 解题 1. 题目 朋友关系列表: Friendship +---------------+---------+ | Column Name | Type | +------ ...

  4. 并查集c++代码_[Leetcode 每日精选](本周主题-并查集) 547. 朋友圈

    题目难度: 中等 原题链接 今天继续来做并查集的问题, 这道题仍然比较基础, 而且也是个比较接近现实的问题了. 大家在我的公众号"每日精选算法题"中的聊天框中回复 并查集 就能看到 ...

  5. python刷leetcode_零基础python刷leetcode -- 3. Longest Substring Without Repeating Characters

    算法很重要,但是每天也需要学学python,于是就想用python刷leetcode 的算法题,和我一起开始零基础python刷leetcode之旅吧.如有不对的地方,希望指正,万分感谢~~ 题目 最 ...

  6. Python JAVA Solutions for Leetcode

    Python & JAVA Solutions for Leetcode (inspired by haoel's leetcode) Remember solutions are only ...

  7. [C/C++基础知识] 面试再谈struct和union大小问题

    最近找工作参加了很多笔试,其中考察结构体和联合体的大小问题是经常出现的一个问题.虽然题目简单而且分值比较低,但是还是想再给大家回顾下这些C和C++的基础知识.希望文章对你有所帮助~         P ...

  8. leetcode 721. Accounts Merge | 721. 账户合并(HashMap版并查集)

    题目 https://leetcode.com/problems/accounts-merge/ 题解 HashMap 版的并查集.参考了:leetcode 684. Redundant Connec ...

  9. leetcode 684. Redundant Connection | 684. 冗余连接(并查集)

    题目 https://leetcode.com/problems/redundant-connection/ 题解 并查集问题 1)有若干个样本a.b.c.d-类型假设是V 2)在并查集中一开始认为每 ...

最新文章

  1. Android 自定义Button按钮显示样式(正常、按下、获取焦点)
  2. 小余学调度:学习记录(2022年1月)
  3. 51nod 1277 KMP 前缀出现次数
  4. 字符串转换成java对象然后通过@RestController返回json对象
  5. pip install 包的安装位置
  6. jpa 自定义sql if_mybatis仿jpa 使用@createDate @updateDate
  7. linux删除文件夹命令6,Linux下创建、删除文件和文件夹命令
  8. ZOJ 1060 Count the Color
  9. 延时队列的几种实现方式(只有原理,并没有源码)
  10. vue连线 插件_使用jsPlumb插件实现动态连线功能
  11. Google Earth Engine APPS(GEE)—— Landsat 数据的时间序列分析来监测森林转化和退化 (CODED)整体框架(万字长文)
  12. Kali linux安装拼音、双拼、五笔拼音输入法:fcitx-table-wbpy中文输入法步骤详解
  13. UG\NX二次开发 获取相切面的三种方法
  14. MATLAB数学经典建模之风扇特性:流量 随 压比函数值变化的图形 (2 维图形)
  15. MMD :maximum mean discrepancy
  16. 虹科ELPRO的智能数据记录仪由Sensirion技术驱动
  17. 应变片原理,小变形测量 http://zy.swust.net.cn/01/1/jzjg0/2/2.3/2.3.htm
  18. UWB地铁隧道人员定位实现运营人员健康智能监测
  19. FPGA:zcu102学习笔记(参考自xing见博客)
  20. 消愁,一杯敬故乡,一杯敬远方

热门文章

  1. MATLAB当中一些简单的数值分析函数总结
  2. MacBook使用与应用推荐
  3. OpenGL之纹理过滤(Texture Filtering)、MipMap方法、纹理坐标
  4. 服务器搭建网站公网ip,如何获取公网ip,自己搭建公网ip服务器的方法
  5. 一本纯属个人的兴趣的书籍即将在未来面世
  6. android最新直播框架,NDK--Android Studio中直播推流框架的搭建
  7. 一文教你用 Neo4j 快速构建明星关系图谱
  8. 2017 年度十大最受欢迎的浏览器,你在用哪一款?
  9. PHP数据跨行跨列处理
  10. EF(Entity Framework、EF Core)