持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
题目描述
在一条无限长的公路上有 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 。
双指针
这个题目我的初步思路是:其实不难分析出小车碰撞的可能性只有两种情况:
- 前车向右,后车静止、或向左
- 前车静止,后车向左
如果前车向左, 后车无论状态是怎么样的,肯定都不会发生碰撞的。那么我们通过双指针来移动处理控制前后车的移动,来进行模拟。具体注意点如下:
开头部分的‘L’和结尾部分的‘R’永远不会相撞,其余的必然会相撞
因为题目只需要求出碰撞次数,所以不需要计算碰撞时间、碰撞车辆等。
我们不用去纠结运动相撞还是静止相撞。
我们可以把运动状态的车权重看为1,静止看为0。运动+运动 = 2 运动+静止= 1,
最后我们可以看出有多少辆车处于运动状态,碰撞次数就会是多少
class Solution {
public int countCollisions(String dir) {
int ans = 0;
char[] arr = dir.toCharArray();
for(int i=1;i<arr.length;i++){
int left=i-1,right=i+1;
int num = 0;
if(arr[left] == 'R'){
// 前车向右
if(arr[i]=='L' || arr[i]=='S'){
//后车向左或静止
while(left>0 && arr[--left] =='R') {
num++;
arr[left]='S';
}
while(right<arr.length-1 && arr[right] =='L') {
num++;
arr[right]='S';
right++;
}
num += (arr[i]=='L' ? 2 : 1);
// i指针移动
i=right==i+1 ? right-1 : right-2;
System.out.println("RS|RL -> i="+i + ",num="+ num);
}
}else if(arr[left] == 'S'){
// 前车静止
if(arr[i]=='L'){
//后车向左
while(right<arr.length-1 && arr[right] =='L') {
num++;
arr[right]='S';
right++;
}
num ++;
// i指针移动
i=right==i+1 ? right-1 : right-2;
System.out.println("SL -> i="+i + ","+ num);
}
}
ans += num;
if (num > 0 ) {
// 有碰撞,则静止
arr[i]='S';
}
}
return ans;
}
}
最后
要WA上几遍才能过这题,唉。