LeetCode第362场周赛
与车相交的点 简单
给你一个下标从 0 开始的二维整数数组 nums
表示汽车停放在数轴上的坐标。对于任意下标i
,nums[i] = [starti, endi]
,其中 starti
是第i
辆车的起点,endi
是第 i
辆车的终点。
返回数轴上被车 任意部分 覆盖的整数点的数目。
示例 1:
输入:nums = [[3,6],[1,5],[4,7]]
输出:7
解释:从 1 到 7 的所有点都至少与一辆车相交,因此答案为 7 。
示例 2:
输入:nums = [[1,3],[5,8]]
输出:7
解释:1、2、3、5、6、7、8 共计 7 个点满足至少与一辆车相交,因此答案为 7 。
提示:
1 <= nums.length <= 100
nums[i].length == 2
1 <= starti <= endi <= 100
分析: 因为数据较小,因此我直接进行了模拟。初始化一个全为0的数组,两层循环,遍历nums,紧接着再从start遍历至end,数组中对应下标的值+1。最终结果为数组中值>0的个数:
代码:
class Solution {
public:
int numberOfPoints(vector<vector<int>>& nums) {
vector<int> v(150,0);int ans=0;
for(int i=0;i<nums.size();i++){
for(int j=nums[i][0];j<=nums[i][1];j++){
v[j]++;
}
}
for(int i=0;i<v.size();i++){
if(v[i]!=0) ans++;
}
return ans;
}
};
优化: 可以利用差分数组思想,将start~end范围内的值均递增,最后统计前缀和中>0的数量。
class Solution {
public:
int numberOfPoints(vector<vector<int>>& nums) {
int v[105],ans=0,tmp=0;
memset(v,0,sizeof(v));
for(auto num : nums){
v[num[0]]++;
v[num[1]+1]--;
}
for(int n : v){
if(tmp+n>0) ans++;
tmp+=n;
}
return ans;
}
};
判断能否在给定时间到达单元格 中等
给你四个整数 sx
、sy
、fx
、fy
以及一个 非负整数 t
。
在一个无限的二维网格中,你从单元格 (sx, sy)
开始出发。每一秒,你 必须 移动到任一与之前所处单元格相邻的单元格中。
如果你能在 恰好 t
秒 后到达单元格 (fx, fy)
,返回 true
;否则,返回 false
。
单元格的 相邻单元格 是指该单元格周围与其至少共享一个角的 8 个单元格。你可以多次访问同一个单元格。
示例 1:
输入:sx = 2, sy = 4, fx = 7, fy = 7, t = 6
输出:true
解释:从单元格 (2, 4) 开始出发,穿过上图标注的单元格,可以在恰好 6 秒后到达单元格 (7, 7) 。
示例 2:
输入:sx = 3, sy = 1, fx = 7, fy = 3, t = 3
输出:false
解释:从单元格 (3, 1) 开始出发,穿过上图标注的单元格,至少需要 4 秒后到达单元格 (7, 3) 。 因此,无法在 3 秒后到达单元格 (7, 3) 。
提示:
1 <= sx, sy, fx, fy <= 109
0 <= t <= 109
分析: 每一个单元格都能有8个方向能走,因此从起点到终点最小的距离为:
s
t
e
p
=
m
a
x
(
a
b
s
(
f
x
−
s
x
)
,
a
b
s
(
f
y
−
s
y
)
)
step = max(abs(fx-sx), abs(fy-sy))
step=max(abs(fx−sx),abs(fy−sy)),因此只需要
t
>
=
s
t
e
p
t>=step
t>=step即可。
但有个坑,当起点终点重叠时,t不能为1.
代码: (我第一次写时,没有想到最小步数的直接计算方法)
class Solution {
public:
bool isReachableAtTime(int sx, int sy, int fx, int fy, int t) {
if(fx==sx&&sy==fy&&t==1) return false;
int a = min(abs(fx-sx), abs(fy-sy));
int b = max(abs(fx-sx), abs(fy-sy))-a;
if(t<a+b)
return false;
else
return true;
}
};
将石头分散到网格图的最少移动次数 中等
给你一个大小为 3 * 3 ,下标从 0 开始的二维整数矩阵 grid ,分别表示每一个格子里石头的数目。网格图中总共恰好有 9 个石头,一个格子里可能会有 多个 石头。
每一次操作中,你可以将一个石头从它当前所在格子移动到一个至少有一条公共边的相邻格子。
请你返回每个格子恰好有一个石头的 最少移动次数 。
示例 1:
输入:grid = [[1,1,0],[1,1,1],[1,2,1]]
输出:3
解释:让每个格子都有一个石头的一个操作序列为:
1 -将一个石头从格子 (2,1) 移动到 (2,2) 。
2 - 将一个石头从格子 (2,2) 移动到 (1,2) 。
3 - 将一个石头从格子(1,2) 移动到 (0,2) 。
总共需要 3 次操作让每个格子都有一个石头。 让每个格子都有一个石头的最少操作次数为 3 。
示例 2:
输入:grid = [[1,3,0],[1,0,0],[1,0,3]]
输出:4
解释:让每个格子都有一个石头的一个操作序列为:
1 - 将一个石头从格子 (0,1) 移动到 (0,2) 。
2 - 将一个石头从格子 (0,1) 移动到 (1,1) 。
3 - 将一个石头从格子(2,2) 移动到 (1,2) 。 4 - 将一个石头从格子 (2,2) 移动到 (2,1) 。
总共需要 4 次操作让每个格子都有一个石头。 让每个格子都有一个石头的最少操作次数为 4 。
提示:
grid.length == grid[i].length == 3
0 <= grid[i][j] <= 9
grid 中元素之和为 9
分析: 比赛过程中,我使用的方法是模拟,但没有考虑到从哪个格子移动石子,对于整体移动次数有影响。
结束后,采取DFS进行搜索,结果超时!
最终根据题解,将石子为0,石子>1的格子分别保存,然后进行搜索。
代码:
class Solution {
public:
int ans=1e4;
void search(vector<vector<int>>& em,vector<vector<int>>& mo, int step,int index){
if(index==em.size()){
if(ans>step){ans=step;return ;}
}
if(step>=ans) return ;
for(int j=0;j<mo.size();j++){
if(mo[j][2]>1){
mo[j][2]--;
search(em, mo, step+abs(em[index][0]-mo[j][0])+abs(em[index][1]-mo[j][1]) ,index+1);
mo[j][2]++;
}
}
}
int minimumMoves(vector<vector<int>>& grid) {
vector<vector<int>> em;
vector<vector<int>> mo;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(grid[i][j]==0) em.push_back({i,j});
else if(grid[i][j]>1) mo.push_back({i,j,grid[i][j]});
}
}
search(em, mo, 0, 0);
return ans;
}
};