• 图论问题建模和floodfill算法


    目录

    引入:leetcode695.岛屿的最大面积

    分析与转换

    一维二维转换

    四联通

    完整代码解答: 

    1)显示的创建图解决问题的代码

    2)不显示的创建图解决此问题的代码

    floodfill算法

    定义


    引入:leetcode695.岛屿的最大面积

    分析与转换:

    在题目中0是海水,1是陆地。在我们自己设定的图中假设蓝色是海水,红色是陆地。且每一个小格子都是一个顶点,若某个红色顶点上下左右方向有另外的红色顶点与它相邻,则在它俩中间连接一条边证明其一同构成了一个岛屿,也就是同属于一个连通分量。这样,我们就把这道题转换成了一个图论的问题。我们要求的问题也就转换成了找出包含顶点最多的连通分量,顶点个数也就是面积的最大值。

    一维二维转换:

    我们还可以通过数学公式将二维和一维相互转换。注意一维是从0开始计数, 二维是从1开始计数。

    四联通:

    我们需要搜索一个红色顶点的上下左右的顶点是否还是陆地,那么如何搜索呢?这就涉及到了四联通的概念。我们可以设立一个二维数组,里面的四个元素代表了相较于本顶点而言,它的行列坐标的位移,也就是表示它的上下左右各移动一个单位的四个坐标。值得注意的是,我们现在的坐标系不是我们熟知的数学坐标系,而是我们计算机一般使用的屏幕坐标系,我们可以理解成二维数组索引所在的坐标系。

    d循环四次代表上下左右四个方向。 

     

     

    完整代码解答: 

    1)显示的创建图解决问题的代码

    1. import java.util.HashSet;
    2. class Solution {
    3. private int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    4. private int R, C;//行数列数
    5. private int[][] grid;
    6. private HashSet[] G;//图的邻接表的表示
    7. private boolean[] visited;
    8. public int maxAreaOfIsland(int[][] grid){
    9. if(grid == null) return 0;
    10. R = grid.length;
    11. if(R == 0) return 0;
    12. C = grid[0].length;
    13. if(C == 0) return 0;
    14. this.grid = grid;
    15. G = constructGraph();//进行建图操作
    16. int res = 0;
    17. visited = new boolean[G.length];
    18. for(int v = 0; v < G.length; v ++){
    19. int x = v / C, y = v % C;
    20. if(grid[x][y] == 1 && !visited[v])//如果v没被遍历过就是证明找到了一个新的岛屿,即一个新的连通分量。
    21. res = Math.max(res, dfs(v));
    22. }
    23. return res;
    24. }
    25. private int dfs(int v){
    26. visited[v] = true;
    27. int res = 1;//1是这是深度优先遍历v这个顶点
    28. for(int w: G[v])
    29. if(!visited[w])
    30. res += dfs(w);
    31. return res;
    32. }
    33. private HashSet[] constructGraph(){
    34. HashSet[] g = new HashSet[R * C];//开辟空间
    35. for(int i = 0; i < g.length; i ++)
    36. g[i] = new HashSet<>();
    37. for(int v = 0; v < g.length; v ++){
    38. int x = v / C, y = v % C;//转换成二维坐标
    39. if(grid[x][y] == 1){//只有它本身是陆地才去判断它四周是否有其他陆地与之相连
    40. for(int d = 0; d < 4; d ++){
    41. int nextx = x + dirs[d][0];
    42. int nexty = y + dirs[d][1];
    43. if(inArea(nextx, nexty) && grid[nextx][nexty] == 1) {//判断nextx和nexty是否合法(是否在网格范围中)
    44. int next = nextx * C + nexty;//转为一维索引
    45. g[v].add(next);//添加一条边
    46. g[next].add(v);
    47. }
    48. }
    49. }
    50. }
    51. return g;
    52. }
    53. private boolean inArea(int x, int y){
    54. return x >= 0 && x < R && y >= 0 && y < C;
    55. }
    56. public static void main(String[] args){
    57. int[][] grid = {{0, 1}};
    58. System.out.println((new Solution()).maxAreaOfIsland(grid));
    59. }
    60. }

    2)不显示的创建图解决此问题的代码

    1. class Solution {
    2. private int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    3. private int R, C;
    4. private int[][] grid;
    5. private boolean[][] visited;
    6. public int maxAreaOfIsland(int[][] grid){
    7. if(grid == null) return 0;
    8. R = grid.length;
    9. if(R == 0) return 0;
    10. C = grid[0].length;
    11. if(C == 0) return 0;
    12. this.grid = grid;
    13. visited = new boolean[R][C];
    14. int res = 0;
    15. for(int i = 0; i < R; i ++)//二重循环遍历每一个顶点
    16. for(int j = 0; j < C; j ++)
    17. if(grid[i][j] == 1 && !visited[i][j])
    18. res = Math.max(res, dfs(i, j));
    19. return res;
    20. }
    21. private int dfs(int x, int y){
    22. visited[x][y] = true;
    23. int res = 1;
    24. for(int d = 0; d < 4; d ++){
    25. int nextx = x + dirs[d][0], nexty = y + dirs[d][1];
    26. if(inArea(nextx, nexty) && grid[nextx][nexty] == 1 && !visited[nextx][nexty])
    27. res += dfs(nextx, nexty);
    28. }
    29. return res;
    30. }
    31. private boolean inArea(int x, int y){
    32. return x >= 0 && x < R && y >= 0 && y < C;
    33. }
    34. }

    floodfill算法

    定义:

    floodfill算法是一种图像处理算法,用于填充连通区域。该算法从一个起始点开始,将所有与该点相邻且颜色相同的像素点都标记为同一区域,并继续递归处理该区域的相邻像素点,直到所有相邻像素点都被标记为该区域。该算法通常用于图像处理、计算机图形学等领域中的填充操作,例如对图像中的某个区域进行颜色填充、图形的边界检测等。

  • 相关阅读:
    【Day17】Java算法刷题 【面试题 01.08. 零矩阵】 【844. 比较含退格的字符串】
    java 16进制浮点数转十进制
    LeetCode(力扣)96. 不同的二叉搜索树Python
    用Python做了几个爬虫私活,赚了
    树、二叉树、斜树、满二叉树、完全二叉树、二叉排序树、平衡二叉搜索树(AVL树) 、哈夫曼树(Huffman tree)、B树、B+Tree、B*树
    如何实现WinApp的UI自动化测试?自动化工具如何选择人?
    double 和 float 的区别
    SpringBoot整合Mybatis方式1:使用XML方式整合Mybatis
    JAVA-LocalDateTime时间格式化,转换时间戳和源码分析
    Python中实现数值交换的四种方式
  • 原文地址:https://blog.csdn.net/xiaoliii0401/article/details/134182086