文章目录
- [1. 图像渲染(LC733)](#1. 图像渲染(LC733))
- [2. 岛屿数量(LC200)](#2. 岛屿数量(LC200))
- [3. 岛屿的最大面积(LC695)](#3. 岛屿的最大面积(LC695))
- [4. 被围绕的区域(LC130)](#4. 被围绕的区域(LC130))
- [5. 太平洋大西洋水流问题(LC417)](#5. 太平洋大西洋水流问题(LC417))
- [6. 扫雷游戏(LC529)](#6. 扫雷游戏(LC529))
- [7. 衣橱整理(LCR130)](#7. 衣橱整理(LCR130))
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;
}
}