题目描述
给定一个数组,包含 $n$ 个正整数。你从起点(0,0)
开始,x[0]
表示往北走的距离,x[1]
表示往西走的距离,x[2]
表示往南走的距离,[x3]
表示往东走的距离,依次类推。换句话说,你一直在按顺时针方向转圈。
请编写一个函数,判断走过的路径是否相交。
只能使用额外 $O(1)$ 的空间。
样例1
给定 x = [2, 1, 1, 2],
?????
? ?
???????>
?
返回 true (路径相交)
样例2
给定 x = [1, 2, 3, 4],
????????
? ?
?
?
?????????????>
返回 false (路径不相交)
样例3
给定 x = [1, 1, 1, 1],
?????
? ?
?????>
返回 true (路径相交)
算法
(分情况讨论) $O(n)$
我们分类讨论相交的情况有哪些。一共有三种:
- 连续的四条边相交:
- 连续的五条边相交:
- 连续的六条边相交:
然后遍历整个数组,判断这三种情况即可。
时间复杂度分析:整个数组仅被遍历一次,所以时间复杂度是 $O(n)$。
C++ 代码
class Solution {
public:
bool isSelfCrossing(vector<int>& x) {
int n = x.size();
if (n <= 3) return false;
for (int i = 3; i < n; i ++ )
{
if (x[i] >= x[i - 2] && x[i - 1] <= x[i - 3]) return true;
if (i >= 4 && x[i - 1] == x[i - 3] && x[i] + x[i - 4] >= x[i - 2]) return true;
if (i >= 5 && x[i - 2] >= x[i - 4] && x[i] + x[i - 4] >= x[i - 2] && x[i - 1] + x[i - 5] >= x[i - 3] && x[i - 1] <= x[i - 3]) return true;
}
return false;
}
};
当个人觉得滑动窗口思路比较好接受.
线段条数小于 4 时,不可能发生交叉。
线段条数大于等于 4 时,开始出现交叉的可能性:
第 4 条线段只可能与第 1 条线段交叉。
第 5 条线段只可能与第 2、1 条线段交叉。
第 6 条线段只可能与第 3、(2)、1 条线段交叉。
第 7 条线段只可能与第 4、(3)、2 条线段交叉(注意,不可能与第 1 条线段交叉,因为路径是逆时针的,此时线段 1 要么被围在内部,要么被抛在外部)
……
从上面分析可以看出,我们至多需要一个大小为 6 的滑动窗口,即可覆盖所有的交叉情况。滑动窗口每移动一步,我们都判断一次新进入窗口的线段与最前面三条线段的交叉关系。
https://leetcode-cn.com/problems/self-crossing/solution/lu-jing-jiao-cha-hua-dong-chuang-kou-jie-fa-by-hzh/