Leetcode题解:335. Self Crossing
难度:Hard
题目
You are given an array x of n positive numbers. You start at point (0,0) and moves x[0] metres to the north, then x[1] metres to the west, x[2] metres to the south, x[3] metres to the east and so on. In other words, after each move your direction changes counter-clockwise.
Write a one-pass algorithm with O(1) extra space to determine, if your path crosses itself, or not.
中文简述
给一串长度为n的正整数,分别表示从(0,0)出发,依次向北、西、南、东四个方向前进对应的长度(也就是按照逆时针方向方形转动)。求写出一条空间复杂度为O(1)的一遍算法检查路径上有无出现交叉的情况。
思路
这道题被定性为难度为Hard的题目,其实只要经过自己的仔细思考,难度并不大,本身没有什么算法上的难点。
首先,由于路径本身是按照逆时针方向,若无交叉则说明路径呈现逆时针向外扩散的回字形或者顺时针向内的回字形。所以可以判断,若出现交叉,最先必定会与本周期或者上一个周期内的边相交。随意我们只需要检查,在扩散过程中有无出现交叉现象,有则算法终止得到交叉的答案,否则一直检查到最后一条边得到无交叉的结果。
首先,我们要总结一共有几种交叉的情况。总的来说我们可以归纳出三种相交的情况如下图。
如上图,我们仅用第一个循环来代表我们3种交叉情况,i用来表示交叉的那条边的编号:
①x[i]>=x[i-2] && x[i-1]<=x[i-3],导致i与i-3相交
②x[i]+x[i-4]>=x[i-2]&&x[i-1]==x[i-3],导致i与i-4相交
③x[i-2] >= x[i-4]&& x[i-3] >= x[i-1]&& x[i]+x[i-4]>=x[i-2]&& x[i-1]+x[i-5]>=x[i-3],导致i与i-5相交
这样我们就可以轻松获得答案代码。
class Solution {
public:
bool isSelfCrossing(vector<int>& x) {
for (int i = 3; i < x.size(); ++i) {
if (x[i]>=x[i-2] && x[i-1]<=x[i-3])
return true;
if (i >= 4 &&x[i]+x[i-4]>=x[i-2]&&x[i-1]==x[i-3])
return true;
if (i >= 5 &&x[i-2] >= x[i-4]&& x[i-3] >= x[i-1]&& x[i]+x[i-4]>=x[i-2]&& x[i-1]+x[i-5]>=x[i-3])
return true;
}
return false;
}
};