Island perimeter.
The general gist of the solution is that, when we peform a dfs, and we are unable to "explore" a neighboring cell, we increment the perimeter (because we treat the neighboring cell as a boundary). The only exception happens, when we attempt to visit an "already explored cell", in that case, we do not increment the island perimeter.
class Solution {
public:
int islandPerimeter(vector<vector<int>>& grid) {
int total_rows = grid.size();
int total_cols = grid[0].size();
int perimeter = 0;
auto cell_value = [&](int row, int col) -> int {
if (row < 0 || row >= total_rows) {
return 0;
}
if (col < 0 || col >= total_cols) {
return 0;
}
return grid[row][col];
};
// The dfs will increment the perimeter
// if the neighboring cell is a water/ out of bounds
// (both represented by the value 0, see the lambda above).
std::function<void(int, int)> dfs = [&](int row, int col) {
grid[row][col] = 2; // 2 marks the cell as visited
{
int top_row = row - 1;
int top_col = col;
if (cell_value(top_row, top_col) == 0) {
perimeter += 1;
}
if (cell_value(top_row, top_col) == 1) {
dfs(top_row, top_col);
}
}
{
int bottom_row = row + 1;
int bottom_col = col;
if (cell_value(bottom_row, bottom_col) == 0) {
perimeter += 1;
}
if (cell_value(bottom_row, bottom_col) == 1) {
dfs(bottom_row, bottom_col);
}
}
{
int left_row = row;
int left_col = col - 1;
if (cell_value(left_row, left_col) == 0) {
perimeter += 1;
}
if (cell_value(left_row, left_col) == 1) {
dfs(left_row, left_col);
}
}
{
int right_row = row;
int right_col = col + 1;
if (cell_value(right_row, right_col) == 0) {
perimeter += 1;
}
if (cell_value(right_row, right_col) == 1) {
dfs(right_row, right_col);
}
}
};
for(int row = 0; row < total_rows; row++) {
for(int col = 0; col < total_cols; col++) {
if(grid[row][col] == 1) {
dfs(row, col);
break;
}
}
}
return perimeter;
}
};