实现 HackerRank 连接单元问题的解决方案

Implementing solution of HackerRank's Connected Cells Question

本文关键字:解决方案 问题 单元 HackerRank 连接 实现      更新时间:2024-09-26

考虑一个矩阵,其中每个单元格都包含0或1。任何包含1的单元格都称为填充单元格。如果两个单元格在水平、垂直或对角方向上相邻,则称其为连接单元格。在下面的网格中,所有标记为X的单元格都连接到标记为Y的单元格。

XXX
XYX  
XXX   

如果一个或多个填充单元格也连接在一起,则它们形成一个区域。注意,一个区域中的每个单元连接到该区域中的零个或多个单元,但不一定直接连接到该区中的所有其他单元。

给定nXm矩阵,查找并打印矩阵中最大区域中的单元格数。请注意,矩阵中可能存在一个以上的区域。

例如:

Sample Input:
5 4
0 0 1 1
0 0 1 0
0 1 1 0
0 1 0 0
1 1 0 0
OUTPUT: 8

我试图解决这个问题,下面是我所尝试的。问题是我在矩阵中的dfs搜索永远不会完成。它在经过一些步骤后终止。我不知道我哪里错了?

#include<bits/stdc++.h>
using namespace std;
bool isValid (int row, int column, int n, int m, bool** visited){
if(row<0 || row>n-1 || column<0 || column>m-1){
return false;
}
if(visited[row][column]==true){
return false;
}
return true;
}
int countConnectedCells(int** arr, int n, int m, bool** visited, int row, int column){
visited[row][column]=1;
int current_maximum=0;

if(arr[row][column]==1){
current_maximum=1;
//Down
if(isValid(row+1,column, n, m, visited)){
current_maximum+=countConnectedCells(arr, n, m, visited, row+1, column);
}
//Right
if(isValid(row,column+1, n, m, visited)){
current_maximum+=countConnectedCells(arr, n, m, visited, row, column+1);
}
//Left
if(isValid(row,column-1, n, m, visited)){
current_maximum+=countConnectedCells(arr, n, m, visited, row, column-1);
}
//Upward
if(isValid(row-1,column, n, m, visited)){
current_maximum+=countConnectedCells(arr, n, m, visited, row-1, column);
}

//UpwardLeft
if(isValid(row-1,column-1, n, m, visited)){
current_maximum+=countConnectedCells(arr, n, m, visited, row-1, column-1);
}
//UpwardRight
if(isValid(row-1,column+1, n, m, visited)){
current_maximum+=countConnectedCells(arr, n, m, visited, row-1, column+1);
}
//DownwardRight
if(isValid(row+1,column+1, n, m, visited)){
current_maximum+=countConnectedCells(arr, n, m, visited, row+1, column+1);
}
//DownLeft
if(isValid(row+1,column-1, n, m, visited)){
current_maximum+=countConnectedCells(arr, n, m, visited, row+1, column-1);
}
}
return current_maximum;
}
int main(){
int n, m;
cin>>n>>m;
int **arr;
bool **visited;
int maximum=0;
/* allocate the array */
arr = (int** )malloc(n * sizeof *arr);
for (int i=0; i<n; i++)
{
arr[i] = (int*)malloc(m * sizeof *arr[i]);
}
/* allocate the visited array */
visited = (bool** )malloc(n * sizeof *visited);
for (int i=0; i<n; i++)
{
visited[i] = (bool*)malloc(m * sizeof *visited[i]);
}

for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>arr[i][j];
}
}
/* dfs call on each cell that has value 1 and is unvisited*/
for(int row=0; row<n; row++){
for(int column=0; column<m; column++){
if(arr[row][column]==1&&isValid(row,column, n, m, visited))
maximum = max(maximum, countConnectedCells(arr, n, m, visited, row, column));
}
}
cout<<maximum<<endl;
/* deallocate the array */
for (int i=0; i<n; i++)
{
free(arr[i]);
}
}

编辑:问题链接

说明

问题是您过早地重置了current_max。它不应该在到达递归堆栈的底部时完成,而应该在完成所有递归调用时完成。

因此,在countConnectedCells()中引入一个局部变量uint32_t current_maximum。删除用于保持当前和全局最大值的全局变量。因此,countConnectedCells可以如下所示:

uint32_t countConnectedCells(int** arr, int n, int m, bool** visited, int row, int column) {
visited[row][column]=1;
uint32_t current_maximum = 0;
if(arr[row][column]==1) {
current_maximum = 1;
//Down
if(isValid(row+1,column, n, m, visited)) {
current_maximum += countConnectedCells(arr, n, m, visited, row+1, column);
}
//Right
if(isValid(row,column+1, n, m, visited)) {
current_maximum += countConnectedCells(arr, n, m, visited, row, column+1);
}
//Left
if(isValid(row,column-1, n, m, visited)) {
current_maximum += countConnectedCells(arr, n, m, visited, row, column-1);
}
//Upward
if(isValid(row-1,column, n, m, visited)) {
current_maximum += countConnectedCells(arr, n, m, visited, row-1, column);
}

//UpwardLeft
if(isValid(row-1,column-1, n, m, visited)) {
current_maximum += countConnectedCells(arr, n, m, visited, row-1, column-1);
}
//UpwardRight
if(isValid(row-1,column+1, n, m, visited)) {
current_maximum += countConnectedCells(arr, n, m, visited, row-1, column+1);
}
//DownwardRight
if(isValid(row+1,column+1, n, m, visited)) {
current_maximum += countConnectedCells(arr, n, m, visited, row+1, column+1);
}
//DownLeft
if(isValid(row+1,column-1, n, m, visited)) {
current_maximum += countConnectedCells(arr, n, m, visited, row+1, column-1);
}
}
return current_maximum;
}

然后,在main()中更改for循环计算最大面积,以便对于每个起始单元格,countConnectedCells返回一个以该单元格为起始单元格的区域,然后在此处更新最大值:

...
/* dfs call on each cell that has value 1 and is unvisited*/
uint32_t maximum = 0;
for(int row=0; row<n; row++){
for(int column=0; column<m; column++){
if(arr[row][column]==1&&isValid(row,column, n, m, visited))
maximum = std::max(maximum, countConnectedCells(arr, n, m, visited, row, column));
}
}
cout<<maximum<<"n";
...

完成此操作后,解决方案运行良好(所有测试都通过(。

改进

实际上,您不需要引入额外的bool数组,因为您可以重用初始数组来标记访问的单元格。您还应该对矩阵使用std::vector,这样就不会手动分配/取消分配数组。还有进一步的改进,你可以-请检查我下面的代码:

#include <bits/stdc++.h>
using namespace std;
uint32_t connectedCell0(uint32_t i, uint32_t j, std::vector<std::vector<uint32_t>> &matrix) {
uint32_t n = matrix.size();
uint32_t m = matrix[0].size();
if (i < 0 || i >= n || j < 0 || j >= m || !matrix[i][j]) {
return 0;
}

//mark as visited
matrix[i][j] = 0;
return 1 + connectedCell0(i, j + 1, matrix) +
connectedCell0(i, j - 1, matrix) +
connectedCell0(i - 1, j - 1, matrix) +
connectedCell0(i - 1, j, matrix) +
connectedCell0(i - 1, j + 1, matrix) +
connectedCell0(i + 1, j - 1, matrix) +
connectedCell0(i + 1, j, matrix) +
connectedCell0(i + 1, j + 1, matrix);
}
// Complete the connectedCell function below.
uint32_t connectedCell(std::vector<std::vector<uint32_t>> &matrix) {
uint32_t maxArea = 0;
for (uint32_t i = 0; i < matrix.size(); i++) {
for (uint32_t j = 0; j < matrix[i].size(); j++) {
if (matrix[i][j]) {
maxArea = max(maxArea, connectedCell0(i, j, matrix));
}
}
std::cout << endl;
}
return maxArea;
}
int main() {
ofstream fout(getenv("OUTPUT_PATH"));
uint32_t n;
std::cin >> n;
std::cin.ignore(numeric_limits<streamsize>::max(), 'n');
uint32_t m;
std::cin >> m;
std::cin.ignore(numeric_limits<streamsize>::max(), 'n');
std::vector<std::vector<uint32_t>> matrix(n);
for (uint32_t i = 0; i < n; i++) {
matrix[i].resize(m);
for (uint32_t j = 0; j < m; j++) {
std::cin >> matrix[i][j];
}
std::cin.ignore(numeric_limits<streamsize>::max(), 'n');
}
uint32_t result = connectedCell(matrix);
fout << result << "n";
fout.close();
return 0;
}