最大岛屿之深度优先搜索(dfs)

本文探讨了一种使用深度优先搜索(DFS)解决矩阵中岛屿面积最大值的问题。通过遍历矩阵,利用栈或递归实现DFS,找到并标记岛屿,更新最大面积。同时,对比了栈和递归两种实现方式,并强调在实际工程中栈可能更为合适,因为其理解和实现直观且不易导致栈溢出。
摘要由CSDN通过智能技术生成

解题思路:使用栈压入弹出,或者使用递归实现
技巧点:自定义搜索方向,使用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)实现深度优先搜索,但因为栈与递归的调用原理相同,而递归相对便于实现,因此刷题时笔者推荐使用递归式写法,同时也方便进行回溯(见下节)。不过在实际工程上,直接使用栈可能才是最好的选择,一是因为便于理解,二是更不易出现递归栈满的情况。我们先展示使用栈的写法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可峰科技

生活不易

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值