-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
125 lines (110 loc) · 3.45 KB
/
main.cpp
File metadata and controls
125 lines (110 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Source: https://leetcode.com/problems/regions-cut-by-slashes
// Title: Regions Cut By Slashes
// Difficulty: Medium
// Author: Mu Yang <http://muyang.pro>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// An `n x n` grid is composed of `1 x 1` squares where each `1 x 1` square consists of a `'/'`, `'\'`, or blank space `' '`. These characters divide the square into contiguous regions.
//
// Given the grid `grid` represented as a string array, return the number of regions.
//
// Note that backslash characters are escaped, so a `'\'` is represented as `'\'`.
//
// **Example 1:**
// https://assets.leetcode.com/uploads/2018/12/15/1.png
//
// ```
// Input: grid = [" /","/ "]
// Output: 2
// ```
//
// **Example 2:**
// https://assets.leetcode.com/uploads/2018/12/15/2.png
//
// ```
// Input: grid = [" /"," "]
// Output: 1
// ```
//
// **Example 3:**
// https://assets.leetcode.com/uploads/2018/12/15/4.png
//
// ```
// Input: grid = ["/\","\/"]
// Output: 5
// Explanation: Recall that because \ characters are escaped, "\/" refers to \/, and "/\" refers to /\.
// ```
//
// **Constraints:**
//
// - `n == grid.length == grid[i].length`
// - `1 <= n <= 30`
// - `grid[i][j]` is either `'/'`, `'\'`, or `' '`.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <numeric>
#include <string>
#include <vector>
using namespace std;
// Union-Find
//
// Treat vertical and horizontal edge of the grid cells as graph node.
// Loop through all grid cells and use union-find to unite them.
//
// Total 2n(n+1) nodes. We use row-major IDs.
// The first half IDs for verticals, and the last half IDs for horizontals.
class Solution {
struct UnionFind {
vector<int> parents;
vector<int> ranks;
int count;
UnionFind(int n) : parents(n), ranks(n, 0), count(n) { //
iota(parents.begin(), parents.end(), 0);
}
int find(int x) {
if (parents[x] != x) {
parents[x] = find(parents[x]);
}
return parents[x];
}
void unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) return;
// Ensure rank(x) >= rank(y)
if (ranks[x] < ranks[y]) swap(x, y);
// Merge y into x
if (ranks[x] == ranks[y]) ++ranks[x];
parents[y] = x;
--count;
}
};
public:
int regionsBySlashes(vector<string>& grid) {
const int n = grid.size();
const int totalNodes = 2 * n * (n + 1);
const int halfTotalNodes = n * (n + 1);
// Helper of IDs
auto verticalID = [n](int r, int c) -> int { return r * (n + 1) + c; };
auto horizontalID = [n, halfTotalNodes](int r, int c) -> int { return r * n + c + halfTotalNodes; };
// Union Find
auto uf = UnionFind(totalNodes);
for (int r = 0; r < n; ++r) {
for (int c = 0; c < n; ++c) {
const char cell = grid[r][c];
const int topID = horizontalID(r, c);
const int bottomID = horizontalID(r + 1, c);
const int leftID = verticalID(r, c);
const int rightID = verticalID(r, c + 1);
if (cell == ' ' || cell == '/') { // merge top+left, bottom+right
uf.unite(topID, leftID);
uf.unite(bottomID, rightID);
}
if (cell == ' ' || cell == '\\') { // merge top+right, bottom+left
uf.unite(topID, rightID);
uf.unite(bottomID, leftID);
}
}
}
return uf.count;
}
};