目录
太平洋大西洋水流问题
题解:
扫雷游戏
题解:
衣橱整理
太平洋大西洋水流问题
417. 太平洋大西洋水流问题 - 力扣(LeetCode)
题解:
如果从区域内某一个位置出发,需要向左、向上走判断是否能到达太平洋,向右、向下走判断是否能到达大西洋,同时能到达太平洋和大西洋的位置,便是我们想要的答案,如果二维矩阵的每一个点都这样判断,时间复杂度很高,我们可以换个方向思考。
假设矩阵中的某一点存在一条路径可以到达太平洋,那么从这一点出发,这条路径中的相邻点的高度是单调递减的(非严格),相反,如果从太平洋出发,这条路径中的相邻点的高度是单调递增的(非严格),到达大西洋的路径也是同理。
那么我们可以从太平洋出发,找一条递增的路径,从大西洋出发,找一条递增的路径,如果这两条路径相交于同一点,那么这个点既可以流向太平洋,也可以流向大西洋。
于是问题转换为建立一个名为 pac 的 bool 类型的二维数组,从太平洋的边界(即第一行、第一列)出发,找出所有的递增路径,并把路径中的每个点标记为 true,大西洋也是同理,二维数组命名为 alt 。寻找递增路径的代码便为 FloodFill 算法。
之后再去遍历二维矩阵 heights:
1、如果 heights[ i ][ j ] 的 pac[ i ][ j ] 和 alt[ i ][ j ] 都为 true,则该点同时可以流向太平洋和大西洋,是我们想要的答案;
2、如果 heights[ i ][ j ] 的 pac[ i ][ j ] 和 alt[ i ][ j ] 有一个为 false,则该点无法同时流向太平洋和大西洋!
class Solution {
int m,n;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
public:
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
m=heights.size(),n=heights[0].size();
vector<vector<bool>> pac(m,vector<bool>(n));
vector<vector<bool>> atl(m,vector<bool>(n));
vector<vector<int>> ret;
for(int i=0;i<n;i++)
{
dfs(heights,pac,0,i);//第一行
dfs(heights,atl,m-1,i);//最后一行
}
for(int i=0;i<m;i++)
{
dfs(heights,pac,i,0);//第一列
dfs(heights,atl,i,n-1);//最后一列
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(pac[i][j] && atl[i][j]) ret.push_back({i,j});
}
}
return ret;
}
void dfs(vector<vector<int>>& heights,vector<vector<bool>>& vis,int i,int j)
{
vis[i][j]=true;
for(int k=0;k<4;k++)
{
int x=i+dx[k],y=j+dy[k];
if(x>=0 && x<m && y>=0 && y<n && !vis[x][y] && heights[x][y]>=heights[i][j])
{
dfs(heights,vis,x,y);
}
}
}
};
扫雷游戏
529. 扫雷游戏 - 力扣(LeetCode)https://leetcode.cn/problems/minesweeper/description/
题解:
这道题相当于给了一个点源:
1、如果该点是未挖出的雷(M),那么把这个雷标记为已挖出(X),并且直接返回盘面;
2、如果该点是未挖出的空方格(E),则把周围方格都递归的揭露:
a.如果方格周围 8 个方格都没有雷,则把该方格标记为 B,且继续递归,继续揭露;
b.如果方格周围 8 个方格存在雷,则标记出雷的个数,且不再递归。
需要注意由于需要访问周围 8 个方格,所以 dx、dy 也需要根据偏移量设置为大小为 8 的数组。
class Solution {
int dx[8]={0,0,1,-1,-1,-1,1,1};
int dy[8]={1,-1,0,0,-1,1,-1,1};
int m,n;
public:
vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
m=board.size(),n=board[0].size();
int x=click[0],y=click[1];
//踩雷
if(board[x][y]=='M')
{
board[x][y]='X';
return board;
}
dfs(board,x,y);
return board;
}
void dfs(vector<vector<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<m && y>=0 && y<n && board[x][y]=='M') ++count;
}
//有地雷
if(count)
{
board[i][j]=count+'0';
return;
}
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<m && y>=0 && y<n && board[x][y]=='E')
{
dfs(board,x,y);//没有地雷的地方继续向外扩展
}
}
}
}
};
衣橱整理
LCR 130. 衣橱整理 - 力扣(LeetCode)https://leetcode.cn/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/description/
这道题只需要向下和向右扩展。
lass Solution {
int dx[2]={0,1};
int dy[2]={1,0};
bool vis[101][101];
public:
int wardrobeFinishing(int m, int n, int cnt) {
int ret=0;
dfs(m,n,0,0,cnt,ret);
return ret;
}
void dfs(int m, int n,int i,int j,int cnt,int& ret)
{
vis[i][j]=true;
++ret;
for(int k=0;k<2;k++)
{
int x=i+dx[k],y=j+dy[k];
if(x>=0 && x<m && y>=0 && y<n && !vis[x][y] && check(x,y,cnt))
dfs(m,n,x,y,cnt,ret);
}
}
bool check(int i,int j,int cnt)
{
int tmp=0;
while(i)
{
tmp+=(i%10);
i/=10;
}
while(j)
{
tmp+=(j%10);
j/=10;
}
if(tmp>cnt) return false;
else return true;
}
};