深度搜索 —— Max Area of Island

来源:互联网 发布:淘宝药店可靠吗 编辑:程序博客网 时间:2024/05/16 16:09

这是一道用深度搜索算法求解的题目。题目内容是这样的:

Given a non-empty 2D array grid of 0’s and 1’s, an island is a group of 1’s (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.
Find the maximum area of an island in the given 2D array. (If there is no island, the maximum area is 0.)

Example

[[0,0,1,0,0,0,0,1,0,0,0,0,0], [0,0,0,0,0,0,0,1,1,1,0,0,0], [0,1,1,0,1,0,0,0,0,0,0,0,0], [0,1,0,0,1,1,0,0,1,0,1,0,0], [0,1,0,0,1,1,0,0,1,1,1,0,0], [0,0,0,0,0,0,0,0,0,0,1,0,0], [0,0,0,0,0,0,0,1,1,1,0,0,0], [0,0,0,0,0,0,0,1,1,0,0,0,0]]  answer:6

从以上例子可以看出题目是这样的,给定一个由 0、1 序列组成的二维数组,1 代表陆地,0 无意义。我们的目标是找到这一个二维平面中连通着的1的最大数量,即为岛屿的最大面积。

我的算法是这样的,遍历整个数组,每找到一个 1,就对这个 1 进行扩展,找到与其连通着的 1,如果没有就回头继续找 1。深度搜索体现在首先对一个方向的所有符合条件的点进行扩展,这个方向扩展结束后再扩展其他方向。当然为了避免扩展已经扩展过的节点,用一个bool类型的二维数组标记每一个点,如果扩展过,该坐标的值就设为true。

扩展的每个点用一个栈来存储,利用栈 LIFO 的特点,当这个栈非空时,取栈顶元素扩展,然后pop掉,扩展得到的点加入到栈中,然后继续取栈顶,直到栈空。这样就经历了与一个 1 连通的所有的 1。

声明一个整型变量,每次扩展一个节点,变量值加一。直到最后得到的就是这个岛屿的面积。我们可能得到多个岛屿的面积,取最大值即可。

代码实现如下:

class Solution {public:    int maxAreaOfIsland(vector<vector<int>> & grid) {        stack<int*> s; // 定义一个栈,用于存放等待遍历的节点        bool test[50][50]; // 一个bool类型的二维数组,用于判断节点是否访问过        for (int i = 0; i < 50; i++) {            for (int j = 0; j < 50; j++) {                test[i][j] = false;            }        }        int maxArea = 0; // 初始化最大面积为0        int row = grid.size(); // 获取grid的高度         int column = grid[0].size(); // 获取grid的宽度        // 用两个数组分别表示水平、垂直方向的节点移动情况        int dr[4] = {-1,0,1,0};        //dr[0] = -1; dr[1] = 0; dr[2] = 1; dr[3] = 0;        int dc[4] = {0,-1,0,1};        //dc[0] = 0; dc[1] = -1; dc[2] = 0; dc[3] = 1;        int x[2500][2];        int cons = 0;        for (int i = 0; i < row; i++) {            for (int j = 0; j < column; j++) {                if (grid[i][j] == 1 && !test[i][j]) { // 遍历grid,如果遇到节点值为1,则将该节点push到栈中,且将该位置的bool值变为true                    int area = 0;                    //int x[2];                    x[cons][0] = i; x[cons][1] = j;                    s.push(x[cons]);                    cons++;                    test[i][j] = true;                     while (!s.empty()) { // 利用栈LIFO的特点,进行深度搜索有效的节点                        int r = s.top()[0];                        int c = s.top()[1];                        area++;                        s.pop(); // 取第一个节点的信息,并将面积加1,然后将栈顶节点pop掉                        for (int k = 0; k < 4; k++) { // 对该节点的四个连通方向的节点进行判断,如果值为1,且尚未被遍历过,则push到栈中                            int nr = r + dr[k];                            int nc = c + dc[k];                            if (nr >= 0 && nr < row && nc >= 0 && nc < column && grid[nr][nc] == 1 && !test[nr][nc]) {                                //int y[2];                                x[cons][0] = nr;                                x[cons][1] = nc;                                s.push(x[cons]);                                cons++;                                test[nr][nc] = true;                            }                        }                    }                    maxArea = maxArea > area ? maxArea : area;                }            }        }        return maxArea;    }};

时间复杂度: O(n2) 数组中的每一个元素都要遍历一次;
空间复杂度: O(n2) 用了一个bool类型的二维数组作为标记,同时栈的使用也有一定的空间占比。

原创粉丝点击