Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
每日刷题第72天 2021.03.23
2211. 统计道路上的碰撞次数
- leetcode原题链接:leetcode-cn.com/problems/co…
- 难度:中等
- 方法:
题目描述
- 在一条无限长的公路上有 n 辆汽车正在行驶。汽车按从左到右的顺序按从 0 到 n - 1 编号,每辆车都在一个 独特的 位置。
- 给你一个下标从 0 开始的字符串 directions ,长度为 n 。directions[i] 可以是 'L'、'R' 或 'S' 分别表示第 i 辆车是向 左 、向 右 或者 停留 在当前位置。每辆车移动时 速度相同 。
- 碰撞次数可以按下述方式计算:
- 当两辆移动方向 相反 的车相撞时,碰撞次数加 2 。
- 当一辆移动的车和一辆静止的车相撞时,碰撞次数加 1 。
- 碰撞发生后,涉及的车辆将无法继续移动并停留在碰撞位置。除此之外,汽车不能改变它们的状态或移动方向。
- 返回在这条道路上发生的 碰撞总次数 。
示例
- 示例1
输入:directions = "RLRSLL"
输出:5
解释:
将会在道路上发生的碰撞列出如下:
- 车 0 和车 1 会互相碰撞。由于它们按相反方向移动,碰撞数量变为 0 + 2 = 2 。
- 车 2 和车 3 会互相碰撞。由于 3 是静止的,碰撞数量变为 2 + 1 = 3 。
- 车 3 和车 4 会互相碰撞。由于 3 是静止的,碰撞数量变为 3 + 1 = 4 。
- 车 4 和车 5 会互相碰撞。在车 4 和车 3 碰撞之后,车 4 会待在碰撞位置,接着和车 5 碰撞。碰撞数量变为 4 + 1 = 5 。
因此,将会在道路上发生的碰撞总次数是 5 。
- 示例2
输入: directions = "LLRR"
输出: 0
解释:
不存在会发生碰撞的车辆。因此,将会在道路上发生的碰撞总次数是 0 。
解题思路
- 根据题意:从左往右模拟每辆车的情况,将车辆
L、R、S记录状态为-1、1、0,然后模拟时分别做以下操作: - 如果当前的车辆是往右走的
R,我们将其标记放入栈中,因为我们向右开的车辆不会影响到左边的结果,也就是说不影响前面的答案 - 如果当前的车辆是往左走的
L,此时根据前面车辆的不同有多种情况:- 1)前面的车辆是
R,此时两车相撞,答案cnt + 2 - 2)前面的车辆是
S,此时两车相撞,答案cnt++
- 1)前面的车辆是
- 当前的车撞完后会变成静止的
S状态,注意此时我们要用这个状态继续去模拟栈里面的前面的状态(因为前面有可能还有往右开的车辆,因为这次相撞会继续撞车),所以将now标记为0状态,继续判断:- 如果当前的车辆是静止的状态(
0),我们判断前面的车辆是否是R状态,只需从栈依次取出前面的车辆状态判断即可,注意记得最后要把此次的状态0放入栈中
- 如果当前的车辆是静止的状态(
脑筋急转弯
- 最左边向左的车 和 最右边向右的车 一定不会相撞
- 中间 L 和 R 的车最终一定会相撞
AC代码
var countCollisions = function(directions) {
// 相反 + 2
// 移动和静止+1
// 碰撞后就会停留
// 返回:碰撞的总次数
let len = directions.length,ans = 0;
let d = directions;
let l = len - 1;
for(let i = 0; i < len; i++) {
if(d[i] == 'R' || d[i] == 'S'){
l = i;
break;
}
}
let r = 0;
for(let i = len - 1; i >= 0; i--) {
if(d[i] == 'L' || d[i] == 'S'){
r = i;
break;
}
}
if(l >= r) return ans;
for(let i = l; i <= r; i++) {
if(d[i] == 'R'){
if(d[i + 1] == 'R') ans++;
else if(d[i + 1] == 'L') ans += 2;
else if(d[i + 1] == 'S') ans++;
}else if(d[i] == 'L'){
if(d[i + 1] == 'L') ans++;
}else if(d[i] == 'S'){
if(d[i + 1] == 'L') ans++;
}
}
return ans;
};
总结
- 分情况进行讨论