【困难】力扣算法题解析LeetCode335:路径交叉

关注文末推广名片,即可免费获得本题测试源码

题目来源:LeetCode 335: 路径交叉

问题抽象: 给定一个整数数组 distance,表示从平面原点 (0,0) 出发的移动路径(按 北→西→南→东 方向循环移动),判断路径是否发生 自交叉

  1. 移动规则

    • i 次移动方向为 directions[i % 4]directions = [北, 西, 南, 东]);
    • 移动距离为 distance[i],每次移动形成一条直线段;
    • 路径累计形成 n 条线段(n = distance.length)。
  2. 交叉判定

    • 仅需检查新添加线段与历史非相邻线段的交叉(相邻线段共享端点,天然不交叉);
    • 交叉包括 线段相交端点重叠(如路径返回原点);
    • 需排除方向循环特性导致的假性交叉(如垂直转弯)。
  3. 优化目标

    • 时间复杂度 O(n)(单次遍历处理),空间复杂度 O(1)(仅存储关键坐标);
    • 利用几何规律:仅当移动步数 ≥4 时才可能交叉,且交叉模式可归纳为有限情况。
  4. 边界处理

    • 数组长度 <4 时默认无交叉(移动 ≤3 次);
    • 长距离移动可能导致 延迟交叉(如第 6 步与第 1 步交叉);
    • 特殊案例:
      • [2,1,1,2] → 交叉(矩形自交);
      • [1,2,3,4] → 无交叉(螺旋展开)。

输入:整数数组 distance1 <= length <= 10^51 <= distance[i] <= 10^5
输出:布尔值(路径自交叉返回 true,否则 false)。


解题思路

本题要求判断给定的移动路径(由一系列移动指令组成)是否会导致路径交叉。移动指令序列中的每个元素表示移动距离,移动方向依次为上、左、下、右并循环重复。路径交叉可能发生在三种情况下:

  1. 第四条线段与第一条线段相交:当第四条线段(右移)的长度大于等于第二条线段(左移)的长度,且第三条线段(下移)的长度小于等于第一条线段(上移)的长度时,路径会交叉。例如 [2,1,1,2]
  2. 第五条线段与第一条线段相交:当第五条线段(上移)的起点位于第一条线段(上移)的延长线上,且第五条线段的长度大于等于第三条线段(下移)的长度减去第一条线段(上移)的长度时,路径会交叉。例如 [1,1,2,1,1]
  3. 第六条线段与第一条线段相交:当第六条线段(左移)的长度大于等于第四条线段(右移)的长度减去第二条线段(左移)的长度,且第五条线段(上移)的长度在特定范围内时,路径会交叉。例如 [1,1,2,2,1,1]

通过遍历移动指令数组,检查每一步是否满足上述三种情况之一,即可判断路径是否交叉。


代码实现(Java版)🔥点击下载源码

class Solution {
    public boolean isSelfCrossing(int[] distance) {
        int n = distance.length;
        // 路径长度小于4时不可能交叉
        if (n < 4) return false;
        
        for (int i = 3; i < n; i++) {
            // 情况1:第四条线段与第一条线段相交
            if (distance[i] >= distance[i-2] && distance[i-1] <= distance[i-3]) {
                return true;
            }
            // 情况2:第五条线段与第一条线段相交
            if (i >= 4) {
                if (distance[i-1] == distance[i-3] && distance[i] >= distance[i-2] - distance[i-4]) {
                    return true;
                }
            }
            // 情况3:第六条线段与第一条线段相交
            if (i >= 5) {
                if (distance[i-2] >= distance[i-4] 
                    && distance[i] >= distance[i-2] - distance[i-4] 
                    && distance[i-1] >= distance[i-3] - distance[i-5] 
                    && distance[i-1] <= distance[i-3]) {
                    return true;
                }
            }
        }
        return false;
    }
}

代码说明

  1. 边界处理:路径长度小于4时,不可能交叉,直接返回 false
  2. 遍历检查:从第四条线段(索引3)开始遍历数组:
    • 情况1:检查第四条线段是否与第一条线段相交(满足 distance[i] >= distance[i-2] && distance[i-1] <= distance[i-3])。
    • 情况2:当 i >= 4 时,检查第五条线段是否与第一条线段相交(满足 distance[i-1] == distance[i-3] && distance[i] >= distance[i-2] - distance[i-4])。
    • 情况3:当 i >= 5 时,检查第六条线段是否与第一条线段相交(满足四个条件:distance[i-2] >= distance[i-4]distance[i] >= distance[i-2] - distance[i-4]distance[i-1] >= distance[i-3] - distance[i-5]distance[i-1] <= distance[i-3])。
  3. 提前返回:满足任一情况立即返回 true,否则遍历结束后返回 false

提交详情(执行用时、内存消耗)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达文汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值