2022-01-29每日刷题打卡
1926. 迷宫中离入口最近的出口
给你一个 m x n 的迷宫矩阵 maze (下标从 0 开始),矩阵中有空格子(用 ‘.’ 表示)和墙(用 ‘+’ 表示)。同时给你迷宫的入口 entrance ,用 entrance = [entrancerow, entrancecol] 表示你一开始所在格子的行和列。
每一步操作,你可以往 上,下,左 或者 右 移动一个格子。你不能进入墙所在的格子,你也不能离开迷宫。你的目标是找到离 entrance 最近 的出口。出口 的含义是 maze 边界 上的 空格子。entrance 格子 不算 出口。
请你返回从 entrance 到最近出口的最短路径的 步数 ,如果不存在这样的路径,请你返回 -1 。
示例 1:
输入:maze = [["+","+",".","+"],[".",".",".","+"],["+","+","+","."]], entrance = [1,2]
输出:1
解释:总共有 3 个出口,分别位于 (1,0),(0,2) 和 (2,3) 。
一开始,你在入口格子 (1,2) 处。
- 你可以往左移动 2 步到达 (1,0) 。
- 你可以往上移动 1 步到达 (0,2) 。
从入口处没法到达 (2,3) 。
所以,最近的出口是 (0,2) ,距离为 1 步。
以题目给的坐标为起点开始广度搜索,向四周扩散,广度搜索结束后遍历一下最外层的四个边,找出最小值。
class Solution {
public:
typedef pair<int,int>PII;
PII que[10010];
int nearestExit(vector<vector<char>>& maze, vector<int>& entrance) {
int m=maze[0].size(),n=maze.size();
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
que[0]={entrance[0],entrance[1]};
maze[entrance[0]][entrance[1]]='+';
vector<vector<int>>v(n,vector<int>(m,0));
int hh=0,tt=0;
while(hh<=tt)
{
auto t=que[hh++];
for(int i=0;i<4;i++)
{
int a=t.first+dx[i],b=t.second+dy[i];
if(a>=0&&a<n&&b>=0&&b<m&&maze[a][b]=='.'&&v[a][b]==0)
{
v[a][b]=v[t.first][t.second]+1;
que[++tt]={a,b};
}
}
}
int res=INT_MAX;
for(int i=0;i<n;i++)
{
if(v[i][0]!=0)res=min(res,v[i][0]);
if(v[i][m-1]!=0)res=min(res,v[i][m-1]);
}
for(int i=0;i<m;i++)
{
if(v[0][i]!=0)res=min(res,v[0][i]);
if(v[n-1][i]!=0)res=min(res,v[n-1][i]);
}
return res==INT_MAX?-1:res;
}
};
1992. 找到所有的农场组
给你一个下标从 0 开始,大小为 m x n 的二进制矩阵 land ,其中 0 表示一单位的森林土地,1 表示一单位的农场土地。
为了让农场保持有序,农场土地之间以矩形的 农场组 的形式存在。每一个农场组都 仅 包含农场土地。且题目保证不会有两个农场组相邻,也就是说一个农场组中的任何一块土地都 不会 与另一个农场组的任何一块土地在四个方向上相邻。
land 可以用坐标系统表示,其中 land 左上角坐标为 (0, 0) ,右下角坐标为 (m-1, n-1) 。请你找到所有 农场组 最左上角和最右下角的坐标。一个左上角坐标为 (r1, c1) 且右下角坐标为 (r2, c2) 的 农场组 用长度为 4 的数组 [r1, c1, r2, c2] 表示。
请你返回一个二维数组,它包含若干个长度为 4 的子数组,每个子数组表示 land 中的一个 农场组 。如果没有任何农场组,请你返回一个空数组。可以以 任意顺序 返回所有农场组。
示例 1:
输入:land = [[1,0,0],[0,1,1],[0,1,1]]
输出:[[0,0,0,0],[1,1,2,2]]
解释:
第一个农场组的左上角为 land[0][0] ,右下角为 land[0][0] 。
第二个农场组的左上角为 land[1][1] ,右下角为 land[2][2] 。
广度搜索,遍历矩阵,找到数值为1的地块时,以那块地块为起点开始广度搜索,整体来说就和岛屿问题差不多,只不过这里返回的不是岛屿的数量,而是岛屿的左上角坐标和右下角坐标,说人话就是,左上角坐标就是x坐标和y坐标是岛屿中最小的,右下角就是最大的。而因为这里的农村都是矩阵,所以我们遍历到的第一个坐标自然就是最小的坐标,即左上角坐标。然后在广度搜索中,找出坐标最大的那个点,即右下角坐标。
class Solution {
public:
typedef pair<int,int>PII;
PII que[100000];
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int n,m;
vector<vector<int>> findFarmland(vector<vector<int>>& land) {
vector<vector<int>>v;
n=land.size(),m=land[0].size();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(land[i][j]==1)
{
vector<int>ans;
ans.push_back(i);
ans.push_back(j);
bfs(land,i,j,ans);
v.push_back(ans);
}
}
}
return v;
}
void bfs(vector<vector<int>>& land,int x,int y,vector<int>&v)
{
que[0]={x,y};
land[x][y]=0;
int hh=0,tt=0;
int max_x=x,max_y=y;
while(hh<=tt)
{
auto t=que[hh++];
for(int i=0;i<4;i++)
{
int a=t.first+dx[i],b=t.second+dy[i];
if(a>=0&&a<n&&b>=0&&b<m&&land[a][b]==1)
{
que[++tt]={a,b};
land[a][b]=0;
max_x=max(max_x,a);
max_y=max(max_y,b);
}
}
}
v.push_back(max_x);
v.push_back(max_y);
}
};
2059. 转化数字的最小运算数
给你一个下标从 0 开始的整数数组 nums ,该数组由 互不相同 的数字组成。另给你两个整数 start 和 goal 。
整数 x 的值最开始设为 start ,你打算执行一些运算使 x 转化为 goal 。你可以对数字 x 重复执行下述运算:
如果 0 <= x <= 1000 ,那么,对于数组中的任一下标 i(0 <= i < nums.length),可以将 x 设为下述任一值:
x + nums[i]
x - nums[i]
x ^ nums[i](按位异或 XOR)
注意,你可以按任意顺序使用每个 nums[i] 任意次。使 x 越过 0 <= x <= 1000 范围的运算同样可以生效,但该该运算执行后将不能执行其他运算。
返回将 x = start 转化为 goal 的最小操作数;如果无法完成转化,则返回 -1 。
示例 1:
输入:nums = [1,3], start = 6, goal = 4
输出:2
解释:
可以按 6 → 7 → 4 的转化路径进行,只需执行下述 2 次运算:
- 6 ^ 1 = 7
- 7 ^ 3 = 4
迷宫问题,区别就是迷宫是在矩阵中上下左右四个方向移动,这里是对数start进行+,-,^,三个操作使其变成goal,准备一个计数器ans=0,每进行一次操作后++。注意的是,这里的数是有界限的,超过0~1000的区间后就没必要记录了,因为记录了也不能进行下一次运算,直接判断是否等于目标值goal即可,如果等于就返回ans+1。顺便还要记录一下每个数的出现情况,如果出现过了就不做处理(出现过了说明也对它做过运算了)。
class Solution {
public:
int minimumOperations(vector<int>& nums, int start, int goal) {
queue<int>que;
vector<int>v(1001);
v[start]++;
que.push(start);
int ans=0,n=nums.size();
while(que.size())
{
int len=que.size();
for(int i=0;i<len;i++)
{
int t=que.front();
que.pop();
if(t==goal)return ans;
if(t>1000||t<0)continue;
for(int j=0;j<n;j++)
{
int o=t+nums[j],p=t-nums[j],q=t^nums[j];
if(o>1000||o<0)
{
if(o==goal)return ans+1;
}
else if(v[o]==0)
{
v[o]=1;
que.push(o);
}
if(p>1000||p<0)
{
if(p==goal)return ans+1;
}
else if(v[p]==0)
{
v[p]=1;
que.push(p);
}
if(q>1000||q<0)
{
if(q==goal)return ans+1;
}
else if(v[q]==0)
{
v[q]=1;
que.push(q);
}
}
}
ans++;
}
return -1;
}
};