【递归、搜索与回溯】FloodFill算法:图像渲染,岛屿数量,岛屿的最大面积,被围绕的区域,太平洋大西洋水流问题,扫雷游戏,衣橱整理

文章目录

1. 图像渲染(LC733)

图像渲染

题目描述

解题思路

从起点向四个方向展开深度优先遍历即可。

代码实现

java 复制代码
class Solution {
    int color;
    int init;
    int m , n;
    public int[][] floodFill(int[][] image, int sr, int sc, int _color) {
        color = _color;
        m = image.length;
        n = image[0].length;

        init = image[sr][sc];
        if(init == color)
            return image;

        image[sr][sc] = color;
        dfs(image,sr,sc);
        return image;

    }
    void dfs(int[][] image,int i,int j){
        int[] dx ={0,0,1,-1};
        int[] dy ={1,-1,0,0};

        for(int k = 0;k<4;k++){
            int x = i+dx[k];
            int y = j+dy[k];
            if(x>=0 && x<m && y>=0 && y<n && image[x][y] == init){
                image[x][y] = color;
                dfs(image,x,y);
            }
        }
    }
}

2. 岛屿数量(LC200)

岛屿数量

题目描述

解题思路

  • 主函数:遍历每一个元素,如果是未标记的就调用dfs深度优先遍历。dfs作用就是把当前元素周围的连通块都遍历并标记。主函数中如果遇到未标记的元素说明是新的连通块,ret++

代码实现

java 复制代码
class Solution {
    boolean[][] check;
    int m,n;
    int ret;
    char[][] grid;
    public int numIslands(char[][] _grid) {
        grid = _grid;
        m = grid.length;
        n = grid[0].length;
        check = new boolean[m][n];
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                if(grid[i][j] == '1' && !check[i][j]){
                    ret++;
                    dfs(i,j);
                }
            }
        }
        return ret;
    }
    void dfs(int i,int j){
        check[i][j] = true;
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};

        for(int k = 0;k<4;k++){
            int x = i+dx[k];
            int y = j+dy[k];
            if(x>=0 && x<m && y>=0 && y<n && !check[x][y] && grid[x][y] == '1'){
                dfs(x,y);
            }
        }
    }
}

3. 岛屿的最大面积(LC695)

岛屿的最大面积

题目描述

解题思路

dfs负责返回搜索过的连通块的面积

代码实现

java 复制代码
class Solution {
    int max,m,n;
    int[][] grid;
    boolean[][] check;
    public int maxAreaOfIsland(int[][] _grid) {
        grid = _grid;
        m = grid.length;
        n = grid[0].length;
        check = new boolean[m][n];
        for(int i = 0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]==1 && !check[i][j])
                    max = Math.max(dfs(i,j),max);
            }
        }
        return max;
    }

    int dfs(int i,int j){
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};
        check[i][j] = true;
        int ret = 1;
        for(int k = 0;k<4;k++){
            int x = dx[k]+i;
            int y = dy[k]+j;
            if(x>=0 && x<m && y>=0 && y<n && !check[x][y] && grid[x][y] == 1)
                ret+=dfs(x,y);
        }
        return ret;
    }
}

4. 被围绕的区域(LC130)

被围绕的区域

题目描述

解题思路

由于边界的O难处理,可以先遍历边界,对边界进行深度优先遍历,修改为'.',接着对数组进行遍历,如果遇到'O'可以直接修改为'x';遇到'.'可以直接修改为'O'

代码实现

java 复制代码
class Solution {
    int m,n;
    public void solve(char[][] board) {
        m = board.length;
        n = board[0].length;
        //遍历边界
        for(int j=0;j<n;j++){
            if(board[0][j] == 'O' )
                dfs(board,0,j);
            if(board[m-1][j] == 'O')
                dfs(board,m-1,j);
        }
        for(int i=0;i<m;i++){
            if(board[i][0] == 'O')
                dfs(board,i,0);
            if(board[i][n-1] == 'O')
                dfs(board,i,n-1);
        }

        //还原
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                if(board[i][j] == '.')
                    board[i][j] ='O';
                else if(board[i][j] == 'O')
                    board[i][j] = 'X';
            }
        }

    }

    void dfs(char[][] board,int i,int j){
        board[i][j] = '.';
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};

        for(int k = 0;k<4;k++){
            int x = dx[k]+i;
            int y = dy[k]+j;

            if(x>=0 && x<m && y>=0 && y<n && board[x][y]=='O')
                dfs(board,x,y);
        }
    }
}

5. 太平洋大西洋水流问题(LC417)

太平洋大西洋水流问题

题目描述

解题思路

由"高处"向"低处"搜索,可能一个元素被遍历很多次,时间复杂度很高。从两个"低处"向"高处"遍历。被标记的公共部分就是可以到达两个区域的岛屿。

代码实现

java 复制代码
class Solution {
    int m,n;
    int[][] heights;
    List<List<Integer>>ret = new ArrayList<>();
    public List<List<Integer>> pacificAtlantic(int[][] _heights) {
        heights = _heights;
        m = heights.length;
        n = heights[0].length;
        boolean[][] pac = new boolean[m][n];
        boolean[][] alt = new boolean[m][n];

        //初始化
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                pac[i][j] = alt[i][j] = false;
            }
        }
        //从低处开始遍历
        for(int i = 0;i<m;i++){
            if(!pac[i][0])
                dfs(i,0,pac);
            if(!alt[i][n-1])
                dfs(i,n-1,alt);
        }
        for(int j = 0;j<n;j++){
            if(!pac[0][j])
                dfs(0,j,pac);
            if(!alt[m-1][j])
                dfs(m-1,j,alt);
        }

        //找公共元素
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                if(pac[i][j] && alt[i][j]){
                    List<Integer> tmp = new ArrayList<>();
                    tmp.add(i);
                    tmp.add(j);
                    ret.add(tmp);
                }
            }
        }
        return ret;
    }

    void dfs(int i ,int j,boolean[][] check){
        check[i][j] = true;
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};
        for(int k=0;k<4;k++){
            int x = i+dx[k];
            int y = j+dy[k];
            if(x>=0 && x<m && y>=0 && y<n && !check[x][y] && heights[x][y]>=heights[i][j])
                dfs(x,y,check);
        }
    }
}

6. 扫雷游戏(LC529)

扫雷游戏

题目描述

解题思路

只需要根据题目要求模拟过程。

  • 向量数组需要8个方向:dx = {1,-1,0,0,1,1,-1,-1},dy = {0,0,1,-1,1,-1,1,-1}
  • 对于每一个空格子都需要检查周围8个格子是否有雷,所以检查雷的过程应该写在dfs

代码实现

java 复制代码
class Solution {
    int m,n;
    int[] dx = {1,-1,0,0,1,1,-1,-1};
    int[] dy = {0,0,1,-1,1,-1,1,-1};
    public char[][] updateBoard(char[][] board, int[] click) {
        m = board.length;
        n = board[0].length;

        int x = click[0];
        int y = click[1];

        //踩雷
        if(board[x][y] == 'M')
            board[x][y] = 'X';
        //空格
        else
            dfs(board,x,y);
        
        return board;
    }

    void dfs(char[][] board,int i,int j){
        //统计周围地雷个数
        int cnt = 0;
        for(int k=0;k<8;k++){
            int x = i+dx[k];
            int y = j+dy[k];
            //有雷
            if(x>=0 && x<m && y>=0 && y<n && board[x][y] == 'M')
                cnt++;
        }

        //有雷,修改为对应数量
        if(cnt>0)
            board[i][j] = (char)('0'+cnt);
        //没有雷,递归展开空格
        else{
            board[i][j] = 'B';
            for(int k=0;k<8;k++){
                int x = i+dx[k];
                int y = j+dy[k];
                if(x>=0 && x<m && y>=0 && y<n && board[x][y] == 'E')
                dfs(board,x,y);
            }
        }
    }
}

7. 衣橱整理(LCR130)

衣橱整理

题目描述

解题思路

从(0,0)开始深搜.

代码实现

java 复制代码
class Solution {
    int m,n,cnt;
    boolean[][] check;
    int[] dx = {1,0};
    int[] dy = {0,1}; 
    public int wardrobeFinishing(int _m, int _n, int _cnt) {
        cnt = _cnt;
        m = _m;
        n = _n;
        check = new boolean[m][n];
        return dfs(0,0);
    }
    int dfs(int i,int j){
        int ret = 1;
        check[i][j] = true;
        for(int k = 0;k<2;k++){
            int x = i + dx[k];
            int y = j + dy[k];
            int sum = 0;
            int tmpx = x;
            int tmpy = y;
            while(tmpx>0 || tmpy >0){
                if(tmpx>0){
                    sum+=(tmpx%10);
                    tmpx/=10;
                }
                if(tmpy>0){
                    sum+=(tmpy%10);
                    tmpy/=10;
                }
            }
            if(x>=0 && x<m && y>=0 && y<n && !check[x][y] && sum<=cnt)
                ret+=dfs(x,y);
        }
        return ret;
    }
}
相关推荐
YUANQIANG20242 小时前
PPO算法典型思路
算法·机器学习
twc8292 小时前
大模型评估指标简要说明
算法·大模型·bleu
淀粉肠kk2 小时前
【C++】C++11可变参数模板和emplace系列接口
算法
ab1515172 小时前
3.21二刷基础125、122、130,完成进阶65
开发语言·c++·算法
j_xxx404_2 小时前
力扣--分治(快速排序)算法题I:颜色分类,排序数组
数据结构·c++·算法·leetcode·排序算法
阿Y加油吧2 小时前
力扣打卡day08——轮转数组、除自身外乘积
数据结构·算法·leetcode
代码探秘者2 小时前
【算法篇】2.滑动窗口
java·数据结构·后端·python·算法·spring
像素猎人2 小时前
数组中的二分查找函数:lower_bound【第一个 >= 目标值的元素的值或者下标】 和 upper_bound【第一个 > 目标值的元素的值或者下标】
数据结构·算法
crediks2 小时前
MTGR(美团生成式推荐框架)总结文档
人工智能·深度学习·算法