当前位置: 首页 > wzjs >正文

江西抚州建设网站营销网站建设免费

江西抚州建设网站,营销网站建设免费,购物网站开发一般使用什么语言,建程网是正规网吗介绍: floodfill算法简单来说就是求出相同性质的联通块 比如在上面这个矩阵中,如果我们要求出所有负数的联通块,就可以使用floodfill算法,但联通必须是上下左右,斜对角的不行 其中实现的方法有深度优先遍历&#xff…

介绍:

floodfill算法简单来说就是求出相同性质的联通块

比如在上面这个矩阵中,如果我们要求出所有负数的联通块,就可以使用floodfill算法,但联通必须是上下左右,斜对角的不行

其中实现的方法有深度优先遍历(dfs)以及宽度优先遍历(bfs),这里主要使用的是dfs

跟之前走迷宫的方法大致一样,难度不大

题目一:

思路:

题意很简单,就是将[sr][sc]的这个值,从这一个点开始,将所有也等于这个值的联通块进行修改,修改成color这个值

这属于floodfill的其中一部分,这道题是只用修改包括起点的这一个联通块,而一般的是需要修改全部的联通块

 因为还是上下左右,所以先搞出方向向量数组,然后根据走迷宫类型的题dfs就行

只不过这里可以不用check记录数组,因为修改为color那么就不等于[sr][sc]了,就不会走重复的路了,当然前提要判断一下color和[sr][sc]不相同,如果相等就之间返回,不用修改了

当然也可以使用check记录数组,那么这样子就无所谓color和[sr][sc]相不相等

总体而言,还是不用check记录数组效率更高,空间节省了,时间也节省了

代码:

class Solution {int row, col;// 方向向量数组int[] dx = { 0, 0, 1, -1 };int[] dy = { 1, -1, 0, 0 };// 值为num的要进行修改int num;public void dfs(int[][] image, int i, int j, int color) {// 进行修改image[i][j] = color;// 上下左右for (int k = 0; k < 4; k++) {int x = i + dx[k], y = j + dy[k];//不越界&&值为numif (x >= 0 && x < row && y >= 0 && y < col && image[x][y] == num) {dfs(image, x, y, color);}}}public int[][] floodFill(int[][] image, int sr, int sc, int color) {// 如果相等就不用修改了if (color == image[sr][sc]) {return image;}row = image.length;col = image[0].length;// 为num赋值num = image[sr][sc];dfs(image, sr, sc, color);return image;}}

题目二:

思路:

 题意很简单,就是求出所有为1的联通块的个数,上一道题是在一个联通块里进行修改,这道题就是找出所有联通块,然后数量加1

也是要有方向向量数组,然后用check来记录走过的陆地,上道题可用可不用,这里就需要用了,当然也可以不用,采用修改为‘0’作为标记,但不推荐,因为修改了原数据,如果要恢复也很麻烦

然后就去遍历数组,如果发现是一块新的岛屿,那么就从该起点开始,去标记所有该岛屿的陆地,最后标记完,结果加1,直到所有数组全部遍历之后,就返回结果

代码:

class Solution {int ret, row, col;// 记录数组boolean[][] check;// 方向向量数组int[] dx = { 0, 0, 1, -1 };int[] dy = { 1, -1, 0, 0 };public void dfs(char[][] grid, int i, int j) {// 修改标记check[i][j] = true;// 上下左右for (int k = 0; k < 4; k++) {int x = i + dx[k], y = j + dy[k];// 如果没越界&&是陆地&&没走过if (x >= 0 && x < row && y >= 0 && y < col && grid[x][y] == '1' && check[x][y] == false) {dfs(grid, x, y);}}}public int numIslands(char[][] grid) {row = grid.length;col = grid[0].length;check = new boolean[row][col];// 遍历数组for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {// 找到一块新岛屿if (grid[i][j] == '1' && check[i][j] == false) {dfs(grid, i, j);ret++;}}}return ret;}
}

题目三:

思路:

 和上一道题基本一样,只是求最大面积,那么我们按照之前思路,去找到每一个联通块,然后统计这一个联通块的面积,如果比现在的max还要大,就更新,否则就不更新

这里设计dfs可以有返回值也可以没有返回值,但思路都是一样的

代码1(有返回值):

class Solution {int ret, row, col;//记录数组boolean[][] check;//方向向量数组int[] dx = { 0, 0, 1, -1 };int[] dy = { 1, -1, 0, 0 };public int dfs(int[][] grid, int i, int j) {//当前陆地面积int sumall=1;//修改标记为走过了check[i][j] = true;//上下左右for (int k = 0; k < 4; k++) {int x = i + dx[k], y = j + dy[k];if (x >= 0 && x < row && y >= 0 && y < col && grid[x][y] == 1 && check[x][y] == false) {//加上这个方向的联通块面积sumall+=dfs(grid, x, y);}}//返回包括该陆地的联通块面积return sumall;}public int maxAreaOfIsland(int[][] grid) {row = grid.length;col = grid[0].length;check = new boolean[row][col];//遍历数组for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {//如果是一块新的岛屿if (grid[i][j] == 1 && check[i][j] == false) {//求出这块岛屿(联通块)的面积int sum = dfs(grid, i, j);//选择最大的if(sum>ret){ret=sum;}}}}//返回最大面积return ret;}
}

代码2:(没有返回值):

class Solution {int ret, row, col;//记录数组boolean[][] check;//方向向量数组int[] dx = { 0, 0, 1, -1 };int[] dy = { 1, -1, 0, 0 };int sum;public void dfs(int[][] grid, int i, int j) {//当前陆地面积sum++;//修改标记为走过了check[i][j] = true;//上下左右for (int k = 0; k < 4; k++) {int x = i + dx[k], y = j + dy[k];if (x >= 0 && x < row && y >= 0 && y < col && grid[x][y] == 1 && check[x][y] == false) {//加上这个方向的联通块面积dfs(grid, x, y);}}}public int maxAreaOfIsland(int[][] grid) {row = grid.length;col = grid[0].length;check = new boolean[row][col];//遍历数组for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {//如果是一块新的岛屿if (grid[i][j] == 1 && check[i][j] == false) {sum=0;//求出这块岛屿(联通块)的面积dfs(grid, i, j);//选择最大的if(sum>ret){ret=sum;}}}}//返回最大面积return ret;}
}

题目四:

思路:

这道题思维要跳脱一下,不能跟着题目的要求来想,题目要求来捕获被围绕的区域,我们又怎么一开始知道是否是被围绕的区域,只能dfs到非法的位置时候才知道不是被围绕的区域,所以这时候就出现一开始不知道,所以没有进行修改,而之后知道了是不是,但又不好回溯了,就一根筋两头堵了

因此我们要改变为一开始就知道是否是被围绕的区域,所以采用正难则反的策略,题目要求找被围绕的区域,那么我们就先找没被围绕的区域,而这个区域一定在边界

所以我们只要找到所有边界的联通块,然后对其进行标记,比如修改为 ‘.’,然后再遍历整个数组,如果还是O,就说明是被围绕的区域,要修改为X,而是.的就说明不是围绕的区域,因此就恢复成O,最后就修改完成了

而这道题标记就可以采用修改的方式,因为本来就需要我们对原数据进行修改,不用采用标记数组

代码:

class Solution {int row,col;//方向向量数组int[] dx={0,0,1,-1};int[] dy={1,-1,0,0};//将所有边缘为O 的联通块修改为 .public void dfs(char[][] board,int i,int j){//修改board[i][j]='.';//上下左右for(int k=0;k<4;k++){int x=i+dx[k],y=j+dy[k];if(x>=0&&x<row&&y>=0&&y<col&&board[x][y]=='O'){dfs(board,x,y);}}}public void solve(char[][] board) {row=board.length;col=board[0].length;//找第一行和最后一行的边界for(int i=0;i<col;i++){if(board[0][i]=='O'){dfs(board,0,i);}if(board[row-1][i]=='O'){dfs(board,row-1,i);}            }//找中间行的左右边界for(int i=1;i<row-1;i++){if(board[i][0]=='O'){dfs(board,i,0);}if(board[i][col-1]=='O'){dfs(board,i,col-1);}}//遍历数组for(int i=0;i<row;i++){for(int j=0;j<col;j++){//如果是被围绕的区域if(board[i][j]=='O'){board[i][j]='X';}else if(board[i][j]=='.'){//不是被围绕的区域board[i][j]='O';}}}}
}

题目五:

思路:

题意比较难理解,但其实就是判断有哪些点的位置,能够从大到小流向太平洋和大西洋,将这些点全部返回

按照题目要求来想,就是遍历数组,如果从这个位置能到达行坐标-1或者列坐标-1,那么就能到达太平洋,而行列坐标能row/col,那么就能到达大西洋,对此分别进行标记,如果两个标记都有,说明符合题意,则添加,反之就不添加,但每次去dfs的时候,check标记数组都要重置

思路很简单,代码跟之前写的差不多

代码1(超时):

class Solution {int po,ao,row,col;//方向向量数组int[] dx={0,0,1,-1};int[] dy={1,-1,0,0};//结果集List<List<Integer>> ret=new ArrayList<>();public void dfs(int[][] heights,int i,int j,boolean[][] check){//上下左右for(int k=0;k<4;k++){int x=i+dx[k],y=j+dy[k];//如果能到达太平洋if(x==-1||y==-1){//标记po=1;       }else if(x==row||y==col){//大西洋ao=1;}else if(check[x][y]==false&&heights[x][y]<=heights[i][j]){//还没走到尽头check[x][y]=true;dfs(heights,x,y,check);check[x][y]=false;}}}public List<List<Integer>> pacificAtlantic(int[][] heights) {row=heights.length;col=heights[0].length;//遍历数组for(int i=0;i<row;i++){for(int j=0;j<col;j++){//创建一个新的标记数组boolean[][] check=new boolean[row][col];dfs(heights,i,j,check);//如果这个位置能到达太平洋和大西洋if(po==1&&ao==1){List<Integer> list=new ArrayList<>();list.add(i);list.add(j);//添加ret.add(list);//恢复标记po=0;ao=0;}}}return ret;}
}

但是有很多重复了,明明之前深搜走过的路,又走一遍,因此效率很低,这道题也会超时

因此需要修改思路,还是正难则反,既然不确定这个位置是否能够到达太平洋和大西洋,那么就反过来从太平洋和大西洋开始,即边界开始,往上流回去,太平洋能流到的地方就标记太平洋,大西洋能流到的地方就标记大西洋,最后再遍历一遍数组,如果既有大西洋又有太平洋的标记,那么这个点就是可以的

这样避免了走许多重复的路

代码2:

class Solution {int row,col;//标记数组boolean[][] po,ao;//方向向量数组int[] dx={0,0,1,-1};int[] dy={1,-1,0,0};//结果集List<List<Integer>> ret=new ArrayList<>();public void dfs(int[][] heights,int i,int j,boolean[][] check){//在标记数组进行标记check[i][j]=true;//上下左右for(int k=0;k<4;k++){int x=i+dx[k],y=j+dy[k];//如果不越界&&没走过&&往高处流if(x>=0&&x<row&&y>=0&&y<col&&check[x][y]==false&&heights[x][y]>=heights[i][j]){dfs(heights,x,y,check);}}}public List<List<Integer>> pacificAtlantic(int[][] heights) {row=heights.length;col=heights[0].length;//太平洋标记数组po=new boolean[row][col];//大西洋标记数组ao=new boolean[row][col];//遍历上下边界for(int j=0;j<col;j++){dfs(heights,0,j,po);dfs(heights,row-1,j,ao);}//遍历左右边界for(int i=0;i<row;i++){dfs(heights,i,0,po);dfs(heights,i,col-1,ao);}//遍历数组for(int i=0;i<row;i++){for(int j=0;j<col;j++){//如果既有太平洋又有大西洋的标记if(po[i][j]&&ao[i][j]){List<Integer> list=new ArrayList<>();list.add(i);list.add(j);//添加ret.add(list);}}}return ret;}
}

题目六:

思路:

题意比较难理解,简单来说就是给你一个棋盘,其中一开始只有M,E,然后会再告诉你一个坐标,这个坐标就是点击的意思,然后这时候就要返回点击之后棋盘的样子,空方格用B表示,周围有地雷,但这里有两种情况,一种是周围既有地雷又有空方格的,就返回个数,如果周围有地雷,但是没有空方格的,就不挖开,还是用E表示

如果运气背的,一开始就点到地雷,那么就将M改成X,剩下不变直接返回就好

其实这道题就是模拟的题,题目告诉你做法,只用实现就行,方法也告诉了用递归,也就是深搜(dfs),考察代码能力而已

这道题是八个方向的,所以方向向量数组要添加对角线方向,简单画一下x,y坐标变化情况,很容易知道dx:1,1,-1,-1分别对应dy:1,-1,1,-1

每深搜到一个格子就先遍历八个方向的格子,如果有地雷,就统计个数,并修改成对应个数,然后停止dfs,如果没有地雷,修改当前格子为B,继续深搜八个方向的

这样子,周围有空格子的一定会遍历到,而周围没有空格子的就还是为E

代码:

class Solution {int row,col;//八个方向向量数组int[] dx={0,0,1,-1,1,1,-1,-1};int[] dy={1,-1,0,0,-1,1,-1,1};public void dfs(char[][] board,int i,int j){//周围雷的数量int count=0;//八个方向去找雷for(int k=0;k<8;k++){int x=i+dx[k],y=j+dy[k];//如果没越界&&有雷if(x>=0&&x<row&&y>=0&&y<col&&board[x][y]=='M'){//个数加1count++;}}//如果周围有雷if(count!=0){//修改为雷的个数board[i][j]=(char)(count+'0');}else{//周围没雷//修改为空格子board[i][j]='B';//继续深搜八个方向for(int k=0;k<8;k++){int x=i+dx[k],y=j+dy[k];//如果没越界&&没找过的格子if(x>=0&&x<row&&y>=0&&y<col&&board[x][y]=='E'){dfs(board,x,y);}}}        }public char[][] updateBoard(char[][] board, int[] click) {row=board.length;col=board[0].length;//如果开局点到雷if(board[click[0]][click[1]]=='M'){board[click[0]][click[1]]='X';return board;}dfs(board,click[0],click[1]);return board;}
}

题目七:

这一版的题目不容易看懂,如果看不懂的话可以看下面原版的题目

 

思路:

原版的题目给了操作步骤,所以要容易理解一些,就是从(0,0)开始,可以进行四个方向的移动,如果这个格子的x和y坐标的数位和(也就是每一位数的和)小于等于k,就能走,统计数加一,否则就不能走

而新版中虽然不好理解,但是也不是一无是处,新版提醒了只能向右和向下移动,为什么呢,因为向上和向左是之前走过的格子,数位之和一定小于k(因为向上的x坐标少1,向左的y坐标少1),因此接下来只有往数位更大的方向走,那就是向右和向下了(因为向下的x坐标多1,向右的y坐标多1)

那么求数位和就很简单,就是/10和%10这些操作,不多讲了

代码:

class Solution {int row,col;//能走的格子个数int count;//记录数组boolean[][] check;public void dfs(int i,int j,int k){//修改标记代表检查过了check[i][j]=true;//数位和int sum=0;//记录原来的i,j坐标int bi=i;int bj=j;//求i的数位和while(i!=0){sum+=i%10;i/=10;}//求j的数位和while(j!=0){sum+=j%10;j/=10;}//如果数位和小于等于kif(sum<=k){//这个格子能走count++;//往右走&&没检查过if(bj+1<col&&check[bi][bj+1]==false){dfs(bi,bj+1,k);}//往下走&&没检查过if(bi+1<row&&check[bi+1][bj]==false){dfs(bi+1,bj,k);}}}public int wardrobeFinishing(int m, int n, int cnt) {row=m;col=n;check=new boolean[row][col];//从(0,0)开始走dfs(0,0,cnt);return count;}
}

总结:

其实跟之前也没什么太大的区别,主要学到了一个正难则反的思想,其他还是老样子

http://www.dtcms.com/wzjs/402303.html

相关文章:

  • 开发网站企业营销网站建设服务
  • 产品营销方案策划书seo在线网站推广
  • 一流的网站建设哪家好沈阳今日新闻头条
  • 二手房网站平台怎么做sem数据分析
  • 教育网站建设方案全网营销国际系统
  • 自己做网站的流程视频抖音关键词推广怎么做
  • 桂林网站建设公司浏览器大全
  • 优秀网站设计案例分析ppt网络营销包括
  • 怎么只做自己的电商网站百度法务部联系方式
  • 线上调研问卷在哪个网站上做手机百度下载免费安装
  • 怎么在商务委的网站做变更淘宝关键词推广
  • 区总工会加强网站意识形态建设北京seo网站优化培训
  • 哪些网站可以做批发衣服谷歌搜索引擎下载安装
  • 昆明网站建设优化在线培训系统
  • 万户网站管理系统4.0站长工具推荐网站
  • 网站做淘客 还可以吗b站免费推广app大全
  • 国外设计网站都有哪些广告公司业务推广
  • 72搭建网站网页百度识图网页版在线
  • 制作网页一般需要兼容哪些网站百度 营销怎么收费
  • 企业网站设计中应注意产品发布功能优化百度网页版电脑版
  • 青岛公司做网站网络营销专员的就业前景
  • 做网站备案时间潜江seo
  • 28网站怎么做代理目前引流最好的app
  • 网站建设常出现的问题企业建站模板
  • 网站模板包含哪些内容学电脑在哪里报名
  • python 做视频网站数据分析网站
  • 网站建设php教程视频网络营销策划的目的
  • 找外包公司做网站网络营销推广论文
  • 网站中的文字滑动怎么做百度推广官网登录
  • 网站优化服务合同上海网络优化seo