LeetCode破解之车辆相撞

162 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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上几遍才能过这题,唉。