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.
Example 1:
Given x = [2, 1, 1, 2]
,
┌───┐
│ │
└───┼──>
│
Return true (self crossing)
Example 2:
Given x = [1, 2, 3, 4]
,
┌──────┐
│ │
│
│
└────────────>
Return false (not self crossing)
Example 3:
Given x = [1, 1, 1, 1]
,
┌───┐
│ │
└───┼>
Return true (self crossing)
解题思路:
1. 判断数组x.length是否小于4,是的话返回false;
2. 判断第三条边x[2]与第一条边x[0]相比是否相等或者更短,如果是,会变成如下图所示的情况,由外向内的螺旋,能够很简单地判断是否是self crossing,只需在循环中不断地判断x[i] 与 x[i-2]的长度,x[i] >= x[i-2]即返回true;
3. 继第2步,如果x[2]>x[0],那么情况变得很复杂,可能会出现如下图所示的各种情况,后两图包含由外向内的螺旋;
4. 哎呀,说不清楚,总之代码如下:
public class Solution {
public boolean isSelfCrossing(int[] x) {
if(x.length < 4)return false;//数组x长度小于4直接返回
if(x[2] <= x[0]){//代表上述第二步中所描述的情况
return isScrew(x, 3);
}else if(x.length > 4){
if(x[3] < x[1]){
if(x[4] >= x[2])return true;//对应第三步图四
else return isScrew(x, 4);//对应第三步图五
}else if(x[3] == x[1]){
if(x[4] >= x[2]-x[0])return true;//一个矩形框框
else if(5<x.length) return isScrew(x, 5);//和第三步图二很像,只不过x[1]==x[3]
else return false;
}else{
for(int i=5; i<x.length; i++){
if(x[i-1] < x[i-3]-x[i-5])return isScrew(x, i);//第三步图三
else if(x[i-1] <= x[i-3]){
if(x[i] >= x[i-2]-x[i-4])return true;//第三步图一
else return isScrew(x, i+1);
}else continue;
}
}
return false;
}
private boolean isScrew(int[] x, int cur){//看能不能一直由外而内地转下去
for(int i=cur; i<x.length; i++){
if(x[i] < x[i-2])continue;
else return true;
}
return false;
}
}