查并集
题目如下:
- 如今有11个元素(1-10),我们设置一定的规则,例如输入<a,b>,则代表a,b属于一个集合,若此时还有规则输入<b,c>,则代表a,b,c属于同一个集合。
- 首先给定一系列的规则输入<a,b>,规定集合分布。
- 最后输入测试样例<x,y>,判断x,y是否属于一个集合
思路如下:
首先我们定义一个friendMap,其中存储:<x,y>表示x的根节点是y
首先存储以下内容:
- <1,1>,<2,2> ~~~~~~<10,10>
表示此时每一个元素的根节点都是自己,即每一个元素都是一个独立的集合。
//定义有10个元素
int[] data = new int[]{1,2,3,4,5,6,7,8,9,10};
HashMap<Integer,Integer> friendMap = new HashMap<>();
//先定义每元素的父节点都是自己
for(int i = 0; i < data.length; i++) friendMap.put(data[i],data[i]);
之后我们输入<a,b>进行合并集操作:即输入a,b元素,找到a元素的根节点,同时找到b元素的根节点,将其进行合并。
public static void merge(HashMap<Integer,Integer> friendMap, int a, int b){
int friendRoota = getRoot(friendMap,a);
int friendRootb = getRoot(friendMap,b);
//找到两个元素的根节点,将这两个根节点合并 合并的顺序可以颠倒
if(friendRoota != friendRootb){
friendMap.put(friendRootb,friendRoota);
}
}
例如此时输入:<2,5>
- friendRoota = 2;
- friendRootb = 5;
- 此时将map中的<5,5> 修改为<5,2>,这就代表5的根节点是2
此时map中存的的元素是:
<1,1> <2,2> <5,2>等等
例如此时输入:<1,5>
- friendRoota = 1;
- friendRootb = 2;
- 此时将map中的<2,2> 修改为 <2,1>,这就代表2的根节点是1
此时map中存的元素是:
<1,1> <2,1> <5,2>等等
所以此时其实可以发现其实我们将5 ——> 2——> 1 生成了一课树,这就类似于将这三个元素变成了一个集合,并且是有关联的。但是实际上,我们的map中最好将value变为key的根root,而不是像此时5存储的value是2,并不是根root:1。
因此在getRoot()方法中我们不仅要返回元素的根root,并且每次都需要将元素的value修改为根root,因此方法如下:
public static int getRoot(HashMap<Integer,Integer> friendMap, int num){
if(friendMap.get(num) == num){
return num;
}
//我们在查找的时候如果发现其中有元素是一个并集的 但是此时他的根节点还未来得及修改,那么就进行修改
//及每次经过一次查找,这个并集中的所有元素的value都会指向根root节点(这个并集的根)
int temp = getRoot(friendMap,friendMap.get(num));
friendMap.put(num,temp);
return temp;
}
全部代码如下:
import java.util.HashMap;
public class test2 {
public static void main(String[] args) {
//定义有10个元素
int[] data = new int[]{1,2,3,4,5,6,7,8,9,10};
HashMap<Integer,Integer> friendMap = new HashMap<>();
//先定义每元素的父节点都是自己
for(int i = 0; i < data.length; i++) friendMap.put(data[i],data[i]);
//开始合并元素
int[][] friends = new int[][]{{2,5},{1,5}};
for(int i = 0; i < friends.length; i++){
merge(friendMap,friends[i][0],friends[i][1]);
}
//测试
int[][] nums = new int[][]{{1,5}};
for(int i = 0; i < nums.length; i++){
int i1 = getRoot(friendMap, nums[i][0]);
int i2 = getRoot(friendMap, nums[i][1]);
if(i1 == i2) System.out.println("true");
else System.out.println("false");
}
System.out.println();
}
public static void merge(HashMap<Integer,Integer> friendMap, int a, int b){
int friendRoota = getRoot(friendMap,a);
int friendRootb = getRoot(friendMap,b);
//找到两个元素的根节点,将这两个根节点合并 合并的顺序可以颠倒
if(friendRoota != friendRootb){
friendMap.put(friendRootb,friendRoota);
}
}
public static int getRoot(HashMap<Integer,Integer> friendMap, int num){
if(friendMap.get(num) == num){
return num;
}
//我们在查找的时候如果发现其中有元素是一个并集的 但是此时他的根节点还未来得及修改,那么就进行修改
//及每次经过一次查找,这个并集中的所有元素的value都会指向根root节点(这个并集的根)
int temp = getRoot(friendMap,friendMap.get(num));
friendMap.put(num,temp);
return temp;
}
}