leetcode 547. 省份数量 Number of provinces 并查集(disjoint set) 路径压缩(compressed path) 深度优先搜索DFS 广度优先搜索BFS

本文通过深度优先搜索DFS和广度优先搜索BFS,结合并查集disjoint set,详细解析LeetCode 547题——如何计算地图中不相交的省份数量。路径压缩技巧提升效率。
摘要由CSDN通过智能技术生成

文章目录


https://leetcode-cn.com/problems/number-of-provinces/

并查集 disjoint set

class Solution {
public:
    int cityNum = 0;  //城市数量
    int *parent = nullptr;  //记录并查集每个节点的父节点
    int *rank = nullptr;  //记录并查集每个节点的深度

    void initialize() {
    	//初始化并查集
        parent = new int[cityNum]();  
        rank = new int[cityNum]();  //并查集每个节点深度为0
        for (int i = 0; i < cityNum; i++) {
        	/*
			  并查集每个节点的父节点为 -1, 
			  -1 表示没有父节点, 
			  即代表为根节点。
			*/
            parent[i] = -1;  
        }
    }

    int find_root(int x) {
    	//寻找并查集中节点的父节点
        int xRoot = x;  //xRoot 为 x 的根节点, 初始为自己
        while (parent[xRoot] != -1) {  //如果 parent[xRoot] == -1, xRoot 即为 x 的根节点
            xRoot = parent[xRoot];  //如果 parent[xRoot] != -1, xRoot 还有父节点, 我们要寻找到 x 的根节点
        }
        return xRoot;
    }

    void merge(int x, int y) {
    	//连接 x 和 y 节点
        int xRoot = find_root(x);  //xRoot 为 x 的根节点
        int yRoot = find_root(y);  //yRoot 为 y 的根节点

        if (xRoot == yRoot) {  //如果 x 与 y 的根节点相同, x 与 y 已经相连
            return;
        }
        
		//路径压缩
		/*
		  如果 xRoot 的深度大于 yRoot 的深度,
		  把 yRoot 的父节点设为 xRoot,
		  这样 xRoot 的深度没有增加, yRoot 也没有增加。
		  如果反过来, yRoot 的深度就等于 xRoot 的深度加 1, 
		  这样持续下去, 深度就会变成最长, 一条直线。
		*/
        if (rank[xRoot] > rank[yRoot]) {
            parent[yRoot] = xRoot;
        }
        else if (rank[yRoot] > rank[xRoot]) {
            parent[xRoot] = yRoot;
        }
        else {
        /*
          如果 xRoot 和 yRoot 的深度相同, 
          随机设置,
          这里选择 xRoot 的父节点设置为 yRoot, 
          yRoot 的深度加 1。
        */
            parent[xRoot] = yRoot;
            rank[yRoot]++;
        }
    }

    int findCircleNum(vector<vector<int>>& isConnected) {
        cityNum = isConnected.size();  //获取城市数量
        initialize();  //初始化并查集

        for (int i = 0; i < cityNum - 1; i++) {
            for (int j = i + 1; j < cityNum; j++) {
                if (isConnected[i][j])
                	/*
                	  遍历无向图所有情况,
                	  如果相连,
                	  调用 merge 方法将两个节点连接起来。
                	*/
                    merge(i, j);
            }
        }

        int proNum = 0;  //省份数量
        for (int i = 0; i < cityNum; i++) {
            if (parent[i] == -1) {
            	/*
            	  有多少个根节点就有多少个省份
            	*/
                proNum++;
            }
        }
        return proNum;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值