解题思路:使用栈压入弹出,或者使用递归实现
技巧点:自定义搜索方向,使用vector direction{-1, 0, 1, 0, -1};
数据实例
std::vector<std::vector<int>> grid = {{1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 1, 1, 1},
{0, 0, 0, 1, 0, 0, 1, 1}};
代码
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
vector<int> direction{-1, 0, 1, 0, -1};
int maxAreaOfIsland(vector<vector<int>> &grid)
{
int m = grid.size(), n = m ? grid[0].size() : 0, local_area, area = 0, x, y;
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
if (grid[i][j])
{
local_area = 1;
grid[i][j] = 0;
stack<pair<int, int>> island;
island.push({i, j});
while (!island.empty())
{
//auto [r, c] = island.top();
pair<int, int> it = island.top();
island.pop();
for (int k = 0; k < 4; ++k)
{
x = it.first + direction[k], y = it.second + direction[k + 1];
if (x >= 0 && x < m &&
y >= 0 && y < n && grid[x][y] == 1)
{
grid[x][y] = 0;
++local_area;
island.push({x, y});
}
}
}
area = max(area, local_area);
}
}
}
return area;
}
int maxArea(std::vector<std::vector<int>> &island)
{
int maxArea = 0;
int maxAreatemp = 0;
for (int i = 0; i < island.size(); i++)
{
for (int j = 0; j < island[0].size(); j++)
{
if (island[i][j] == 1)
{
island[i][j] = 0;
stack<pair<int, int>> temp;
temp.push(pair<int, int>(i, j));
maxAreatemp = 1;
while (!temp.empty())
{
pair<int, int> index = temp.top();
temp.pop();
for (int k = 0; k < 4; k++)
{
int r = index.first + direction[k];
int l = index.second + direction[k + 1];
if (r >= 0 && r < island.size() && l >= 0 && l < island[0].size())
{
if (island[r][l] == 1)
{
temp.push(pair<int, int>(r, l));
island[r][l] = 0;
maxAreatemp++;
}
}
}
}
std::cout << "maxAreatemp " << maxAreatemp << std::endl;
maxArea = max(maxArea, maxAreatemp);
}
}
}
return maxArea;
}
// 辅函数
int dfs(vector<vector<int>> &grid, int r, int c)
{
if (grid[r][c] == 0)
return 0;
grid[r][c] = 0;
int x, y, area = 1;
for (int i = 0; i < 4; ++i)
{
x = r + direction[i], y = c + direction[i + 1];
if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size())
{
area += dfs(grid, x, y);
}
}
return area;
}
int maxAreaOfIsland2(vector<vector<int>> &grid)
{
if (grid.empty() || grid[0].empty())
return 0;
int max_area = 0;
for (int i = 0; i < grid.size(); ++i)
{
for (int j = 0; j < grid[0].size(); ++j)
{
if (grid[i][j] == 1)
{
max_area = max(max_area, dfs(grid, i, j));
}
}
}
return max_area;
}
int dfs_n(std::vector<std::vector<int>> &grid, int r, int l)
{
//std::cout << "r = " << r << " l = " << l << " -> " << grid[r][l] << std::endl;
int area = 0;
if (grid[r][l] == 0)
return 0;
grid[r][l] = 0;
area++;
for (int i = 0; i < 4; i++)
{
int r_ = r + direction[i];
int l_ = l + direction[i + 1];
//std::cout << "r_ " << r_ << " l_ " << l_ << std::endl;
if (r_ >= 0 && r_ < grid.size() && l_ >= 0 && l_ < grid[0].size())
{
//std::cout << "LOOP " << " r_ " << r_ << " l_ " << l_ <<std::endl;
area += dfs_n(grid, r_, l_);
}
}
return area;
}
int maxArea2(std::vector<std::vector<int>> &grid)
{
int maxArea = 0;
for (int i = 0; i < grid.size(); i++)
{
for (int j = 0; j < grid[0].size(); j++)
{
if (grid[i][j] == 0)
continue;
std::cout << "---------------------------- "
<< "i = " << i << " j = " << j << " -> " << grid[i][j] << std::endl;
maxArea = max(maxArea, dfs_n(grid, i, j));
std::cout << "maxArea " << maxArea << std::endl;
}
}
return maxArea;
}
int main(int, char **)
{
std::cout << "Hello, world!\n";
std::vector<std::vector<int>> grid = {{1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 1, 1, 1},
{0, 0, 0, 1, 0, 0, 1, 1}};
// std::vector<int> grid_1 = {1, 0, 1, 1, 0, 1, 0, 1};
// std::vector<int> grid_2 = {1, 0, 1, 1, 0, 1, 1, 1};
// std::vector<int> grid_3 = {0, 0, 0, 0, 0, 0, 0, 1};
// grid.push_back(grid_1);
// grid.push_back(grid_2);
// grid.push_back(grid_3);
std::cout << maxArea2(grid) << std::endl;
}
高畅 Chang Gao说:一般来说,深度优先搜索类型的题可以分为主函数和辅函数,主函数用于遍历所有的搜索位置,判断是否可以开始搜索,如果可以即在辅函数进行搜索。辅函数则负责深度优先搜索的递归调用。当然,我们也可以使用栈(stack)实现深度优先搜索,但因为栈与递归的调用原理相同,而递归相对便于实现,因此刷题时笔者推荐使用递归式写法,同时也方便进行回溯(见下节)。不过在实际工程上,直接使用栈可能才是最好的选择,一是因为便于理解,二是更不易出现递归栈满的情况。我们先展示使用栈的写法。