实现并查集类,解决连通性问题。(比如:朋友圈) 思路:把问题抽象成带有索引的数组。根据索引进行连通,从而得到连通个数。
class UnionFind{private:vector<int> parent;vector<int> rank;int count; // 省份个数public:UnionFind(unsigned int size){for (int i = 0; i < size; i++) {parent.push_back(i); // 自己的祖先是自己rank.push_back(1); // 圈子大小初始状态都为1}count = size;}int Find(int p){while (p != parent[p]) {// TODO:路径压缩parent[p] = parent[parent[p]]; // 路径压缩, 可减少一倍,也可不压缩p = parent[p];}return p;// return p == parent[p] ? p : parent[p] = Find(parent[p]);}void UnionElement(int p, int q){int pRoot = Find(p);int qRoot = Find(q);if (qRoot == pRoot) {return;}// 小圈子融入大圈子if (rank[pRoot] < rank[qRoot]) {parent[pRoot] = qRoot; // 不用维护层数} else if (rank[pRoot] > rank[qRoot]) {parent[qRoot] = pRoot; // 不用维护层数} else {parent[qRoot] = pRoot;rank[pRoot]++; // 层数加1}count--;}int size() {return count; // 返回圈子的个数}};class Solution {public:int findCircleNum(vector<vector<int>>& isConnected){UnionFind *unionFind = new UnionFind(isConnected.size());for (int i = 0; i < isConnected.size(); i++) {for(int j = 0; j < isConnected[0].size(); j++) {if (isConnected[i][j] == 1) {unionFind->UnionElement(i, j);}}}return unionFind->size();}};
1. 题目
1631. 最小体力消耗路径
你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动,你想要找到耗费 体力 最小的一条路径。
一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。
请你返回从左上角走到右下角的最小 体力消耗值 。
解决思路:1、二分+BFS。2、并查集、3、二分+DFS
// 并查集模板class UnionFind{private:vector<int> parent;vector<int> rank;int count; // 省份个数public:UnionFind(unsigned int size){for (int i = 0; i < size; i++) {parent.push_back(i); // 自己的祖先是自己rank.push_back(1); // 圈子大小初始状态都为1}count = size;}int Find(int p){while (p != parent[p]) {// TODO:路径压缩parent[p] = parent[parent[p]]; // 路径压缩, 可减少一倍,也可不压缩p = parent[p];}return p;// return p == parent[p] ? p : parent[p] = Find(parent[p]);}void UnionElement(int p, int q){int pRoot = Find(p);int qRoot = Find(q);if (qRoot == pRoot) {return;}// 小圈子融入大圈子if (rank[pRoot] < rank[qRoot]) {parent[pRoot] = qRoot; // 不用维护层数} else if (rank[pRoot] > rank[qRoot]) {parent[qRoot] = pRoot; // 不用维护层数} else {parent[qRoot] = pRoot;rank[pRoot]++; // 层数加1}count--;}int Size() {return count; // 返回圈子的个数}bool Connected(int p, int q){return Find(p) == Find(q);}};class Solution {public:static bool cmp(tuple<int, int, int>& a, tuple<int, int, int>& b){return get<2>(a) < get<2>(b);}int minimumEffortPath(vector<vector<int>>& heights){int m = heights.size();int n = heights[0].size();vector<tuple<int, int, int>> edges;for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {int id = i * n + j; // 标记点的方式if (i > 0) {int id1 = (i - 1) * n + j; // 往上的点edges.emplace_back(id1, id, abs(heights[i][j] - heights[i - 1][j]));}if (j > 0) {int id1 = i * n + j - 1; // 往左的点edges.emplace_back(id1, id, abs(heights[i][j] - heights[i][j - 1]));}}}sort(edges.begin(), edges.end(), cmp);UnionFind uf(m * n);int ans = 0;for (const auto [x, y, v]: edges) {uf.UnionElement(x, y);if (uf.Connected(0, m * n - 1)) {ans = v;break;}}return ans;}};
