省份数量-经典的分组算法
https://www.bilibili.com/video/BV1Jv411A7Ty?p=34
比如现在有三个城市:A城市、B城市、C城市,其中 A 城市与 B城市相连,C城市与A、B城市都不相连。
画图展示:
然后我们得到的数组是这样的:
例如:A城市与自己相连,A城市与B城市相连,A城市与C不相连,所以得到:{1,1,0 } 。后面两个城市的关系也是类似,不再描述…
所以最终用数组表示三个城市的关系是这样的:
{
{
1,1,0 } , {
1,1,0 } , {
0, 0, 1} }
这里说明一下我们的入参和出参,入参是一个城市关系的数组,出参是省份数量。 省份数量是这样认定的,比如我们上面提到的A、B、C 城市关系,出参就是 2 ,我们认为只要是关联的的城市,就在同一个省份。
所以:
{
1,0,0 } , {
0,1,0 } , {
0, 0, 1}
此数组的城市关系出参为 3,也就是说有三个省份。
1、深度优先遍历
https://www.bilibili.com/video/BV1Jv411A7Ty?p=35
//1、深度优先遍历
public static int getProvince(int[][] citysConnected){
int citys=citysConnected.length;
boolean[] visited = new boolean[citys];
int provinces=0;//计数器
for (int i = 0; i < citys; i++) {
if(!visited[i]){
//递归,深度优先
dfs(i,citys,visited,citysConnected);
provinces++;
}
}
return provinces;
}
private static void dfs(int i, int citys, boolean[] visited, int[][] citysConnected) {
for (int j = 0; j < citys; j++) {
if(citysConnected[i][j]==1 && !visited[j]){
visited[j]=true;
dfs(j,citys,visited,citysConnected);
}
}
}
2、广度优先
https://www.bilibili.com/video/BV1Jv411A7Ty?p=36
//2、广度优先
public static int getProvince1(int[][] citysConnected){
int citys=citysConnected.length;
boolean[] visited = new boolean[citys];
int provinces=0;//计数器
Queue<Integer> queue=new LinkedList<Integer>();
for (int i = 0; i < citys; i++) {
if(!visited[i]){
queue.offer(i);
while (!queue.isEmpty()){
int k=queue.poll();
visited[k]=true;
for (int j = 0; j <citys ; j++) {
if(citysConnected[i][j]==1 && !visited[j]){
queue.offer(j);
}
}
}
provinces++;
}
}
return provinces;
}
3、并查集 算法
https://www.bilibili.com/video/BV1Jv411A7Ty?p=37
//3、并查集
private static int mergeFind(int[][] citysConnected){
int citys = citysConnected.length;
int[] head=new int[citys];
int[] level=new int[citys];
for (int i = 0; i <citys ; i++) {
head[i]=i;
level[i]=1;
}
for (int i = 0; i <citys ; i++) {
for (int j = i+1; j <citys ; j++) {
if(citysConnected[i][j]==1){
merge(i,j,head,level);
}
}
}
int count=0;
for (int i = 0; i <citys ; i++) {
if(head[i]==i){
count++;
}
}
return count;
}
//合并
private static void merge(int x, int y, int[] head, int[] level){
int i=find(x,head);
int j=find(y,head);
//如果根节点一样
if(i==j){
return;
}
if(level[i] <= level[j]){
head[i]=j;
}else {
head[j]=i;
}
if(level[i]==level[j]){
level[i]++;
level[j]++;
}
}
//查找
private static int find(int x,int[] head){
if(head[x]==x){
return x;
}
head[x]=find(head[x],head);
return head[x];
}
实验源码
package com.example.rabbitmq;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.LinkedList;
import java.util.Queue;
@SpringBootTest
/*
省份数量
*/
class SuanfaApplicationTests20 {
//1、深度优先遍历
public static int getProvince(int[][] citysConnected){
int citys=citysConnected.length;
boolean[] visited = new boolean[citys];
int provinces=0;//计数器
for (int i = 0; i < citys; i++) {
if(!visited[i]){
//递归,深度优先
dfs(i,citys,visited,citysConnected);
provinces++;
}
}
return provinces;
}
private static void dfs(int i, int citys, boolean[] visited, int[][] citysConnected) {
for (int j = 0; j < citys; j++) {
if(citysConnected[i][j]==1 && !visited[j]){
visited[j]=true;
dfs(j,citys,visited,citysConnected);
}
}
}
//2、广度优先
public static int getProvince1(int[][] citysConnected){
int citys=citysConnected.length;
boolean[] visited = new boolean[citys];
int provinces=0;//计数器
Queue<Integer> queue=new LinkedList<Integer>();
for (int i = 0; i < citys; i++) {
if(!visited[i]){
queue.offer(i);
while (!queue.isEmpty()){
int k=queue.poll();
visited[k]=true;
for (int j = 0; j <citys ; j++) {
if(citysConnected[i][j]==1 && !visited[j]){
queue.offer(j);
}
}
}
provinces++;
}
}
return provinces;
}
//3、并查集
private static int mergeFind(int[][] citysConnected){
int citys = citysConnected.length;
int[] head=new int[citys];
int[] level=new int[citys];
for (int i = 0; i <citys ; i++) {
head[i]=i;
level[i]=1;
}
for (int i = 0; i <citys ; i++) {
for (int j = i+1; j <citys ; j++) {
if(citysConnected[i][j]==1){
merge(i,j,head,level);
}
}
}
int count=0;
for (int i = 0; i <citys ; i++) {
if(head[i]==i){
count++;
}
}
return count;
}
//合并
private static void merge(int x, int y, int[] head, int[] level){
int i=find(x,head);
int j=find(y,head);
//如果根节点一样
if(i==j){
return;
}
if(level[i] <= level[j]){
head[i]=j;
}else {
head[j]=i;
}
if(level[i]==level[j]){
level[i]++;
level[j]++;
}
}
//查找
private static int find(int x,int[] head){
if(head[x]==x){
return x;
}
head[x]=find(head[x],head);
return head[x];
}
@Test
public void sf0(){
//城市关系 1
int[][] city1=new int[][]{
{
1,1,0 } , {
1,1,0 } , {
0, 0, 1} };
//城市关系 2
int[][] city2=new int[][]{
{
1,0,0 } , {
0,1,0 } , {
0, 0, 1} };
System.out.println("--------深度优先--------");
System.out.println(getProvince(city1));
System.out.println(getProvince(city2));
System.out.println("--------广度优先--------");
System.out.println(getProvince1(city1));
System.out.println(getProvince1(city2));
System.out.println("--------并查集--------");
System.out.println(mergeFind(city1));
System.out.println(mergeFind(city2));
}
}
结果:
--------深度优先--------
2
3
--------广度优先--------
2
3
--------并查集--------
2
3