给定由N行和M列组成的布尔矩阵mat [] [] ,最初填充0 ‘s(空单元格),整数K并查询类型{X,Y}的Q [] [] ,则任务为替换mat [X] [Y] = 1 (非空单元)并计算给定矩阵中连接的非空单元的数量。
例子:
Input: N = 3, M = 3, K = 4, Q[][] = {{0, 0}, {1, 1}, {1, 0}, {1, 2}}
Output: 1 2 1 1
Explanation:
Initially, mat[][] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}
Query 1: mat[][] = {{1, 0, 0}, {0, 0, 0}, {0, 0, 0}}, Count = 1
Query 1: mat[][] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 0}}, Count = 2
Query 1: mat[][] = {{1, 0, 0}, {1, 1, 0}, {0, 0, 0}}, Count = 1
Query 1: mat[][] = {{1, 0, 0}, {1, 1, 1}, {0, 0, 0}}, Count = 1
Input: N = 2, M = 2, K = 2, Q[][] = {{0, 0}, {0, 1}}
Output : 1 1
方法:
使用不交集数据结构可以解决该问题。请按照以下步骤解决问题:
- 由于最初矩阵中没有1 ,因此count = 0 。
- 通过执行线性映射索引= X * M + Y ,将二维问题转换为经典的Union-find,其中M为列长。
- 在每个查询中设置索引后,递增计数。
- 如果四个相邻单元格中的任何一个都存在非空单元格:
- 对当前索引和相邻单元格执行“联合”操作(连接两个集合)。
- 连接两个Set时的递减计数。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Count of connected cells
int ctr = 0;
// Function to return the representative
// of the Set to which x belongs
int find(vector& parent, int x)
{
// If x is parent of itself
if (parent[x] == x)
// x is representative
// of the Set
return x;
// Otherwise
parent[x] = find(parent, parent[x]);
// Path Compression
return parent[x];
}
// Unites the set that includes
// x and the set that includes y
void setUnion(vector& parent,
vector& rank, int x, int y)
{
// Find the representatives(or the
// root nodes) for x an y
int parentx = find(parent, x);
int parenty = find(parent, y);
// If both are in the same set
if (parenty == parentx)
return;
// Decrement count
ctr--;
// If x's rank is less than y's rank
if (rank[parentx] < rank[parenty]) {
parent[parentx] = parenty;
}
// Otherwise
else if (rank[parentx] > rank[parenty]) {
parent[parenty] = parentx;
}
else {
// Then move x under y (doesn't matter
// which one goes where)
parent[parentx] = parenty;
// And increment the result tree's
// rank by 1
rank[parenty]++;
}
}
// Function to count the number of
// connected cells in the matrix
vector solve(int n, int m,
vector >& query)
{
// Store result for queries
vector result(query.size());
// Store representative of
// each element
vector parent(n * m);
// Initially, all elements
// are in their own set
for (int i = 0; i < n * m; i++)
parent[i] = i;
// Stores the rank(depth) of each node
vector rank(n * m, 1);
vector grid(n * m, 0);
for (int i = 0; i < query.size(); i++) {
int x = query[i].first;
int y = query[i].second;
// If the grid[x*m + y] is already
// set, store the result
if (grid[m * x + y] == 1) {
result[i] = ctr;
continue;
}
// Set grid[x*m + y] to 1
grid[m * x + y] = 1;
// Increment count.
ctr++;
// Check for all adjacent cells
// to do a Union with neighbour's
// set if neighbour is also 1
if (x > 0 and grid[m * (x - 1) + y] == 1)
setUnion(parent, rank,
m * x + y, m * (x - 1) + y);
if (y > 0 and grid[m * (x) + y - 1] == 1)
setUnion(parent, rank,
m * x + y, m * (x) + y - 1);
if (x < n - 1 and grid[m * (x + 1) + y] == 1)
setUnion(parent, rank,
m * x + y, m * (x + 1) + y);
if (y < m - 1 and grid[m * (x) + y + 1] == 1)
setUnion(parent, rank,
m * x + y, m * (x) + y + 1);
// Store result.
result[i] = ctr;
}
return result;
}
// Driver Code
int main()
{
int N = 3, M = 3, K = 4;
vector > query
= { { 0, 0 },
{ 1, 1 },
{ 1, 0 },
{ 1, 2 } };
vector result = solve(N, M, query);
for (int i = 0; i < K; i++)
cout << result[i] << " ";
}
Java
// Java program to implement
// the above approach
import java.util.*;
class GFG{
// Count of connected cells
static int ctr = 0;
// Function to return the representative
// of the Set to which x belongs
static int find(int []parent, int x)
{
// If x is parent of itself
if (parent[x] == x)
// x is representative
// of the Set
return x;
// Otherwise
parent[x] = find(parent, parent[x]);
// Path Compression
return parent[x];
}
// Unites the set that includes
// x and the set that includes y
static void setUnion(int[] parent,
int[] rank, int x, int y)
{
// Find the representatives(or the
// root nodes) for x an y
int parentx = find(parent, x);
int parenty = find(parent, y);
// If both are in the same set
if (parenty == parentx)
return;
// Decrement count
ctr--;
// If x's rank is less than y's rank
if (rank[parentx] < rank[parenty])
{
parent[parentx] = parenty;
}
// Otherwise
else if (rank[parentx] > rank[parenty])
{
parent[parenty] = parentx;
}
else
{
// Then move x under y (doesn't matter
// which one goes where)
parent[parentx] = parenty;
// And increment the result tree's
// rank by 1
rank[parenty]++;
}
}
// Function to count the number of
// connected cells in the matrix
static int [] solve(int n, int m,
int [][]query)
{
// Store result for queries
int []result = new int[query.length];
// Store representative of
// each element
int []parent = new int[n * m];
// Initially, all elements
// are in their own set
for(int i = 0; i < n * m; i++)
parent[i] = i;
// Stores the rank(depth) of each node
int []rank = new int[n * m];
Arrays.fill(rank, 1);
boolean []grid = new boolean[n * m];
for(int i = 0; i < query.length; i++)
{
int x = query[i][0];
int y = query[i][1];
// If the grid[x*m + y] is already
// set, store the result
if (grid[m * x + y] == true)
{
result[i] = ctr;
continue;
}
// Set grid[x*m + y] to 1
grid[m * x + y] = true;
// Increment count.
ctr++;
// Check for all adjacent cells
// to do a Union with neighbour's
// set if neighbour is also 1
if (x > 0 && grid[m * (x - 1) + y] == true)
setUnion(parent, rank,
m * x + y, m * (x - 1) + y);
if (y > 0 && grid[m * (x) + y - 1] == true)
setUnion(parent, rank,
m * x + y, m * (x) + y - 1);
if (x < n - 1 && grid[m * (x + 1) + y] == true)
setUnion(parent, rank,
m * x + y, m * (x + 1) + y);
if (y < m - 1 && grid[m * (x) + y + 1] == true)
setUnion(parent, rank,
m * x + y, m * (x) + y + 1);
// Store result.
result[i] = ctr;
}
return result;
}
// Driver Code
public static void main(String[] args)
{
int N = 3, M = 3, K = 4;
int [][]query = { { 0, 0 },
{ 1, 1 },
{ 1, 0 },
{ 1, 2 } };
int[] result = solve(N, M, query);
for(int i = 0; i < K; i++)
System.out.print(result[i] + " ");
}
}
// This code is contributed by Amit Katiyar
Python3
# Python 3 program to implement
# the above approach
# Count of connected cells
ctr = 0
# Function to return the
# representative of the Set
# to which x belongs
def find(parent, x):
# If x is parent of itself
if (parent[x] == x):
# x is representative
# of the Set
return x
# Otherwise
parent[x] = find(parent,
parent[x])
# Path Compression
return parent[x]
# Unites the set that
# includes x and the
# set that includes y
def setUnion(parent,
rank, x, y):
global ctr
# Find the representatives
# (or the root nodes) for x an y
parentx = find(parent, x)
parenty = find(parent, y)
# If both are in the same set
if (parenty == parentx):
return
# Decrement count
ctr -= 1
# If x's rank is less than y's rank
if (rank[parentx] < rank[parenty]):
parent[parentx] = parenty
# Otherwise
elif (rank[parentx] > rank[parenty]):
parent[parenty] = parentx
else:
# Then move x under y
# (doesn't matter which
# one goes where)
parent[parentx] = parenty
# And increment the result
# tree's rank by 1
rank[parenty] += 1
# Function to count the number of
# connected cells in the matrix
def solve(n, m, query):
global ctr
# Store result for queries
result = [0] * len(query)
# Store representative of
# each element
parent = [0] * (n * m)
# Initially, all elements
# are in their own set
for i in range (n * m):
parent[i] = i
# Stores the rank(depth)
# of each node
rank = [1] * (n * m)
grid = [0] * (n * m)
for i in range (len( query)):
x = query[i][0]
y = query[i][1]
# If the grid[x*m + y] is already
# set, store the result
if (grid[m * x + y] == 1):
result[i] = ctr
continue
# Set grid[x*m + y] to 1
grid[m * x + y] = 1
# Increment count.
ctr += 1
# Check for all adjacent cells
# to do a Union with neighbour's
# set if neighbour is also 1
if (x > 0 and
grid[m * (x - 1) + y] == 1):
setUnion(parent, rank,
m * x + y,
m * (x - 1) + y)
if (y > 0 and
grid[m * (x) + y - 1] == 1):
setUnion(parent, rank,
m * x + y,
m * (x) + y - 1)
if (x < n - 1 and
grid[m * (x + 1) + y] == 1):
setUnion(parent, rank,
m * x + y,
m * (x + 1) + y)
if (y < m - 1 and
grid[m * (x) + y + 1] == 1):
setUnion(parent, rank,
m * x + y,
m * (x) + y + 1)
# Store result.
result[i] = ctr
return result
# Driver Code
if __name__ == "__main__":
N = 3
M = 3
K = 4
query = [[0, 0],
[1, 1],
[1, 0],
[1, 2]]
result = solve(N, M, query)
for i in range (K):
print (result[i], end = " ")
# This code is contributed by Chitranayal
C#
// C# program to implement
// the above approach
using System;
class GFG{
// Count of connected cells
static int ctr = 0;
// Function to return the representative
// of the Set to which x belongs
static int find(int []parent, int x)
{
// If x is parent of itself
if (parent[x] == x)
// x is representative
// of the Set
return x;
// Otherwise
parent[x] = find(parent, parent[x]);
// Path Compression
return parent[x];
}
// Unites the set that includes
// x and the set that includes y
static void setUnion(int[] parent,
int[] rank,
int x, int y)
{
// Find the representatives(or the
// root nodes) for x an y
int parentx = find(parent, x);
int parenty = find(parent, y);
// If both are in the same set
if (parenty == parentx)
return;
// Decrement count
ctr--;
// If x's rank is less than y's rank
if (rank[parentx] < rank[parenty])
{
parent[parentx] = parenty;
}
// Otherwise
else if (rank[parentx] > rank[parenty])
{
parent[parenty] = parentx;
}
else
{
// Then move x under y (doesn't matter
// which one goes where)
parent[parentx] = parenty;
// And increment the result tree's
// rank by 1
rank[parenty]++;
}
}
// Function to count the number of
// connected cells in the matrix
static int [] solve(int n, int m,
int [,]query)
{
// Store result for queries
int []result = new int[query.Length];
// Store representative of
// each element
int []parent = new int[n * m];
// Initially, all elements
// are in their own set
for(int i = 0; i < n * m; i++)
parent[i] = i;
// Stores the rank(depth) of each node
int []rank = new int[n * m];
for(int i = 0; i < rank.Length; i++)
rank[i] = 1;
bool []grid = new bool[n * m];
for(int i = 0; i < query.GetLength(0); i++)
{
int x = query[i, 0];
int y = query[i, 1];
// If the grid[x*m + y] is already
// set, store the result
if (grid[m * x + y] == true)
{
result[i] = ctr;
continue;
}
// Set grid[x*m + y] to 1
grid[m * x + y] = true;
// Increment count.
ctr++;
// Check for all adjacent cells
// to do a Union with neighbour's
// set if neighbour is also 1
if (x > 0 && grid[m * (x - 1) + y] == true)
setUnion(parent, rank,
m * x + y, m * (x - 1) + y);
if (y > 0 && grid[m * (x) + y - 1] == true)
setUnion(parent, rank,
m * x + y, m * (x) + y - 1);
if (x < n - 1 && grid[m * (x + 1) + y] == true)
setUnion(parent, rank,
m * x + y, m * (x + 1) + y);
if (y < m - 1 && grid[m * (x) + y + 1] == true)
setUnion(parent, rank,
m * x + y, m * (x) + y + 1);
// Store result.
result[i] = ctr;
}
return result;
}
// Driver Code
public static void Main(String[] args)
{
int N = 3, M = 3, K = 4;
int [,]query = {{ 0, 0 }, { 1, 1 },
{ 1, 0 }, { 1, 2 }};
int[] result = solve(N, M, query);
for(int i = 0; i < K; i++)
Console.Write(result[i] + " ");
}
}
// This code is contributed by sapnasingh4991
1 2 1 1
时间复杂度: O(N * M * sizeof(Q))
辅助空间: O(N * M)