题目来源:LeetCode 335: 路径交叉
问题抽象: 给定一个整数数组 distance,表示从平面原点 (0,0) 出发的移动路径(按 北→西→南→东 方向循环移动),判断路径是否发生 自交叉。
-
移动规则:
- 第
i次移动方向为directions[i % 4](directions = [北, 西, 南, 东]); - 移动距离为
distance[i],每次移动形成一条直线段; - 路径累计形成
n条线段(n = distance.length)。
- 第
-
交叉判定:
- 仅需检查新添加线段与历史非相邻线段的交叉(相邻线段共享端点,天然不交叉);
- 交叉包括 线段相交 或 端点重叠(如路径返回原点);
- 需排除方向循环特性导致的假性交叉(如垂直转弯)。
-
优化目标:
- 时间复杂度 O(n)(单次遍历处理),空间复杂度 O(1)(仅存储关键坐标);
- 利用几何规律:仅当移动步数
≥4时才可能交叉,且交叉模式可归纳为有限情况。
-
边界处理:
- 数组长度
<4时默认无交叉(移动≤3次); - 长距离移动可能导致 延迟交叉(如第
6步与第1步交叉); - 特殊案例:
[2,1,1,2]→ 交叉(矩形自交);[1,2,3,4]→ 无交叉(螺旋展开)。
- 数组长度
输入:整数数组 distance(1 <= length <= 10^5,1 <= distance[i] <= 10^5)
输出:布尔值(路径自交叉返回 true,否则 false)。
解题思路
本题要求判断给定的移动路径(由一系列移动指令组成)是否会导致路径交叉。移动指令序列中的每个元素表示移动距离,移动方向依次为上、左、下、右并循环重复。路径交叉可能发生在三种情况下:
- 第四条线段与第一条线段相交:当第四条线段(右移)的长度大于等于第二条线段(左移)的长度,且第三条线段(下移)的长度小于等于第一条线段(上移)的长度时,路径会交叉。例如
[2,1,1,2]。 - 第五条线段与第一条线段相交:当第五条线段(上移)的起点位于第一条线段(上移)的延长线上,且第五条线段的长度大于等于第三条线段(下移)的长度减去第一条线段(上移)的长度时,路径会交叉。例如
[1,1,2,1,1]。 - 第六条线段与第一条线段相交:当第六条线段(左移)的长度大于等于第四条线段(右移)的长度减去第二条线段(左移)的长度,且第五条线段(上移)的长度在特定范围内时,路径会交叉。例如
[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;
}
}
代码说明
- 边界处理:路径长度小于4时,不可能交叉,直接返回
false。 - 遍历检查:从第四条线段(索引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])。
- 情况1:检查第四条线段是否与第一条线段相交(满足
- 提前返回:满足任一情况立即返回
true,否则遍历结束后返回false。
提交详情(执行用时、内存消耗)

1632

被折叠的 条评论
为什么被折叠?



