leetcode 200. Number of Islands 、694 Number of Distinct Islands 、695. Max Area of Island 、130. Surro

两种方式处理已经访问过的节点:一种是用visited存储已经访问过的1;另外一种是经过改变原始数值的值,好比将1改为-1,这样小于等于0的都会中止。html

Number of Islands 用了第一种方式,Number of Distinct Islands用了第二种方式数组

 

注意:若是采用更改原数组的方式,必定要注意加引用!!!函数

 

 

Number of Islands变种,假设给的矩阵四周都是陆地,和陆地相连不算island。优化

方法:与Number of Islands的search函数是同样的,只是须要进行预处理 ,即先把与四周的1相连的全变成0,而后再作与Number of Islands同样的操做spa

 

200. Number of Islands .net

我的理解dfs、bfs的时间复杂度都是 o(m*n)code

 

时间复杂度o(m*n)htm

1.这种写法要改变原始输入数组的值blog

错误版本:递归

    条件判断顺序写错:grid[x][y] == '0' || x < 0 || x >= length || y < 0 || y >= width

    这种写法要报数组越界的错误,由于grid[x][y]会先访问,实际上x、y这个时候可能就越界了,grid[x][y]必须放在这几个越界判断的后面

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int length = grid.size();
        if(length <= 0)
            return 0;
        int width = grid[0].size();
        int count = 0;
        for(int i = 0;i < length;i++){
            for(int j = 0;j < width;j++){
                if(grid[i][j] == '1'){
                    search(grid,i,j,length,width);
                    count++;
                }
            }
        }
        return count;
    }
    void search(vector<vector<char>>& grid,int x,int y,int length,int width){
        if(x < 0 || x >= length || y < 0 || y >= width || grid[x][y] == '0')
            return;
        grid[x][y] = '0';
        search(grid,x-1,y,length,width);
        search(grid,x+1,y,length,width);
        search(grid,x,y-1,length,width);
        search(grid,x,y+1,length,width);
    }
};

 

 

总体思路,从第一点开始找1,若是找到1,把全部的与这个1相连的1置为0,由于这些1与这个1属于同一个岛屿,用dfs去找把全部的1找到

https://blog.csdn.net/xudli/article/details/45912547

 

 

2.不改变原始输入的值,仍是用dfs

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int width = grid.size();
        if(width <= 0)
            return 0;
        int length = grid[0].size();
        if(length <= 0)
            return 0;
        int count = 0;
        vector<vector<bool>> visited(width,vector<bool>(length,false));
        for(int i = 0;i < width;i++){
            for(int j = 0;j < length;j++){
                if(grid[i][j] == '1' && visited[i][j] == false){
                    search(grid,i,j,visited);
                    count++;
                }
            }
        }
        return count;
    }
    void search(vector<vector<char>> grid,int x,int y,vector<vector<bool>>& visited){
        if(x < 0 || x >= grid.size() || y < 0 || y >= grid[0].size() || grid[x][y] == '0' || visited[x][y] == true)
            return;
        visited[x][y] = true;
        search(grid,x-1,y,visited);
        search(grid,x+1,y,visited);
        search(grid,x,y-1,visited);
        search(grid,x,y+1,visited);
    }
};

 http://www.cnblogs.com/grandyang/p/4402656.html

 

bfs的两种方法:

方法一:

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size();
        if(m <= 0)
            return 0;
        int n = grid[0].size();
        if(n <= 0)
            return 0;
        queue<pair<int,int>> q;
        int res = 0;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if(grid[i][j] == '1'){
                    q.push(make_pair(i,j));
                    res++;
                    grid[i][j] = '0';
                    while(!q.empty()){
                        int x= q.front().first;
                        int y = q.front().second;
                        q.pop();
                        //grid[x][y] = '0';
                        for(auto dir : dirs){
                            int x_cur = x + dir[0];
                            int y_cur = y + dir[1];
                            if(x_cur < 0 || x_cur >= m || y_cur < 0 || y_cur >= n || grid[x_cur][y_cur] == '0')
                                continue;
                            q.push(make_pair(x_cur,y_cur));
                            grid[x_cur][y_cur] = '0';
                        }
                    }
                }
            }
        }
        return res;
    }
    vector<vector<int>> dirs{{-1,0},{1,0},{0,-1},{0,1}};
};

方法二:

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size();
        if(m <= 0)
            return 0;
        int n = grid[0].size();
        if(n <= 0)
            return 0;
        vector<vector<bool>> visited(m,vector<bool>(n,false));
        queue<pair<int,int>> q;
        int res = 0;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if(grid[i][j] == '1' && visited[i][j] == false){
                    q.push(make_pair(i,j));
                    res++;
                    visited[i][j] = true;
                    while(!q.empty()){
                        int x = q.front().first;
                        int y = q.front().second;
                        q.pop();
                        for(auto dir : dirs){
                            int x_cur = x + dir[0];
                            int y_cur = y + dir[1];
                            if(x_cur < 0 || x_cur >= m || y_cur < 0 || y_cur >= n || grid[x_cur][y_cur] == '0' || visited[x_cur][y_cur] == true)
                                continue;
                            visited[x_cur][y_cur] = true;
                            q.push(make_pair(x_cur,y_cur));
                        }
                    }
                }
            }
        }
        return res;
    }
    vector<vector<int>> dirs{{-1,0},{1,0},{0,-1},{0,1}};
};

 

错误方法一:

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size();
        if(m <= 0)
            return 0;
        int n = grid[0].size();
        if(n <= 0)
            return 0;
        queue<pair<int,int>> q;
        int res = 0;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if(grid[i][j] == '1'){
                    q.push(make_pair(i,j));
                    res++;
                    while(!q.empty()){
                        int x= q.front().first;
                        int y = q.front().second;
                        q.pop();
                        grid[x][y] = '0';
                        for(auto dir : dirs){
                            int x_cur = x + dir[0];
                            int y_cur = y + dir[1];
                            if(x_cur < 0 || x_cur >= m || y_cur < 0 || y_cur >= n || grid[x_cur][y_cur] == '0')
                                continue;
                            q.push(make_pair(x_cur,y_cur));
                        }
                    }
                }
            }
        }
        return res;
    }
    vector<vector<int>> dirs{{-1,0},{1,0},{0,-1},{0,1}};
};

这个错误的方法与方法一相似,可是这个方法会在大数组的时候报超时,这是由于每次进行将1变成0的操做都是在队列弹出以后,这样会致使许多重复计算。

以下图,从右下角的1开始遍历,会先遍历到左下角和右上角,这种状况没问题,可是当左下角和右上角都要遍历到左上角时,都会把左上角这个1加入队列进行一次计算,可是正确写法却不用。由于正确写法,在加入队列的时候就已经置为0了,下一次再访问到这个位置确定不会再加入队列了。

 

 

694 Number of Distinct Islands 

存储搜索到的每一个岛的形状,利用set来保证存储的形状不同。形状的存储是根据每一个遍历节点到每一个岛的左上点的x、y差值,因此用pair的形式。由于每一个岛有多个点,因此用vector存储

用unordered_set编译会报错

class Solution {
public:
    int numberofDistinctIslands(vector<vector<int>> &grid) {
        int m = grid.size();
        if(m <= 0)
            return 0;
        int n = grid[0].size();
        if(n <= 0)
            return 0;
        set<vector<pair<int,int>>> shapes;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if(grid[i][j] == 1){
                    vector<pair<int,int>> shape;
                    numberofDistinctIslands(grid,i,j,i,j,shape);
                    shapes.insert(shape);
                }
            }
        }
        return shapes.size();
    }
    void numberofDistinctIslands(vector<vector<int>>& grid,int x0,int y0,int i,int j,vector<pair<int,int>>& shape){
        if(i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i][j] <= 0)
            return;
        grid[i][j] = -1;
        shape.push_back({x0 - i ,y0 - j});
        numberofDistinctIslands(grid,x0,y0,i - 1,j,shape);
        numberofDistinctIslands(grid,x0,y0,i + 1,j,shape);
        numberofDistinctIslands(grid,x0,y0,i,j - 1,shape);
        numberofDistinctIslands(grid,x0,y0,i,j + 1,shape);
    }
};

 

695. Max Area of Island

本身写的

记录每一个岛屿的节点个数就行了。每次大的循环是一个岛屿,每次递归是一个节点,因此在每次递归的时候++就行了,而后比较全部岛屿中最大的

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int m = grid.size();
        if(m <= 0)
            return 0;
        int n = grid[0].size();
        if(n <= 0)
            return 0;
        int max_num = 0;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if(grid[i][j] == 1){
                    int num = 0;
                    maxAreaOfIsland(grid,i,j,num);
                    if(num > max_num)
                        max_num = num;
                }
            }
        }
        return max_num;
    }
    void maxAreaOfIsland(vector<vector<int>>& grid,int i,int j,int& num){
        if(i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i][j] <= 0)
            return;
        grid[i][j] = -1;
        num++;
        maxAreaOfIsland(grid,i - 1,j,num);
        maxAreaOfIsland(grid,i + 1,j,num);
        maxAreaOfIsland(grid,i,j - 1,num);
        maxAreaOfIsland(grid,i,j + 1,num);
    }
};

 

130. Surrounded Regions

在4条边上的O确定不会被包围。

在4条边上找O,而后寻找这个O的岛屿,而后把这4条边能生成的岛屿全变成$,最后再将O变成X,$变成O。

这里第一个代码换了一种迭代的写法,每次判断的依据是如下一个节点为依据,后一个代码是本身常用的迭代写法,都是能够的。

class Solution {
public:
    void solve(vector<vector<char> >& board) {
        int m = board.size();
        if(m <= 0)
            return;
        int n = board[0].size();
        if(n <= 0)
            return;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if((i == 0 || i == board.size() -1 || j == 0 || j == board[0].size() - 1) && board[i][j] == 'O')
                    solve(board,i,j);
            }
        }
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if(board[i][j] == 'O')
                    board[i][j] = 'X';
                if(board[i][j] == '$')
                    board[i][j] = 'O';
            }
        }
        return;
    }
    void solve(vector<vector<char> >& board,int i,int j){
        board[i][j] = '$';
        if(i >= 1 && board[i-1][j] == 'O')
            solve(board,i - 1,j);
        if(i < board.size() - 1 && board[i+1][j] == 'O')
            solve(board,i + 1,j);
        if(j >= 1 && board[i][j-1] == 'O')
            solve(board,i,j - 1);
        if(j < board[0].size() - 1 && board[i][j+1] == 'O')
            solve(board,i,j + 1);
        return;
    }
};

本身最常写的。

class Solution {
public:
    void solve(vector<vector<char> >& board) {
        int m = board.size();
        if(m <= 0)
            return;
        int n = board[0].size();
        if(n <= 0)
            return;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if((i == 0 || i == board.size() -1 || j == 0 || j == board[0].size() - 1) && board[i][j] == 'O')
                    solve(board,i,j);
            }
        }
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if(board[i][j] == 'O')
                    board[i][j] = 'X';
                if(board[i][j] == '$')
                    board[i][j] = 'O';
            }
        }
        return;
    }
    void solve(vector<vector<char> >& board,int i,int j){
        if(i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || board[i][j] != 'O')
            return;
        board[i][j] = '$';
        solve(board,i - 1,j);
        solve(board,i + 1,j);
        solve(board,i,j - 1);
        solve(board,i,j + 1);
    }
};

 

并查集:

是否是在一个集合里面
指向本身的优化
hash-map就能够解决

操做:1.查询
     非递归比递归好。每次递归调用,程序保存了上一次调用的结果
     集合表明
   2.合并

434. Number of Islands II(lintcode) 

https://www.cnblogs.com/grandyang/p/5190419.html

n表明行数、m表明列数,x是在行上的位置,y是在列上的位置,因此在roots中的坐标应该是:m * x + y

roots表示全部节点所属于的根,即属于哪个集合,初始为-1表示没有属于任何一个集合。

count表示集合个数,若是自己是一个重来没属于任何结合的位置,遍历到的时候就须要 count++。

核心思路:两个相邻的位置不属于同一个集合,这代表须要更新集合。

class Solution {
public:
    /**
     * @param n: An integer
     * @param m: An integer
     * @param operators: an array of point
     * @return: an integer array
     */
    vector<int> numIslands2(int n, int m, vector<Point> &operators) {
        // write your code here
        vector<int> result;
        int count = 0;
        vector<vector<int>> dirs{{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
        vector<int> roots(m*n,-1);
        for(int i = 0;i < operators.size();i++){
            int x = operators[i].x;
            int y = operators[i].y;
            int index = m * x + y;
            if(roots[index] == -1){
                roots[index] = index;
                count++;
            }
            for(auto dir : dirs){
                int dx = x + dir[0];
                int dy = y + dir[1];
                int cur_index = m * dx + dy;
                if(dx < 0 || dx >= n || dy < 0 || dy >= m || roots[cur_index] == -1)
                    continue;
                int p = findroot(roots,cur_index),q = findroot(roots,index);
                if(p != q){
                    roots[p] = q;
                    count--;
                }
            }
            result.push_back(count);
        }
        return result;
    }
    int findroot(vector<int> roots,int index){
        int root = roots[index];
        while(root != index){
            index = root;
            root = roots[index];
        }
        return root;
    }
};

 

178. Graph Valid Tree

https://www.cnblogs.com/grandyang/p/5257919.html

这道题给了咱们一个无向图,让咱们来判断其是否为一棵树,咱们知道若是是树的话,全部的节点必须是链接的,也就是说必须是连通图,并且不能有环,因此咱们的焦点就变成了验证是不是连通图和是否含有环。

这个题与Number of Islands II的查找操做有点不太同样,Number of Islands II中根节点存储的是本身的下标,这个题的根节点存储的是-1,因此find函数不太同样。

class Solution {
public:
    /**
     * @param n: An integer
     * @param edges: a list of undirected edges
     * @return: true if it's a valid tree, or false
     */
    bool validTree(int n, vector<vector<int>> &edges) {
        // write your code here
        vector<int> roots(n,-1);
        for(int i = 0;i < edges.size();i++){
            int p = findRoot(roots,edges[i][0]);
            int q = findRoot(roots,edges[i][1]);
            if(p == q)
                return false;
            roots[p] = q;
        }
        return edges.size() == n-1; 
    }
    int findRoot(vector<int> roots,int index){
        while(roots[index] != -1)
            index = roots[index];
        return index;
    }
};
相关文章
相关标签/搜索