Total Accepted: 1941
Total Submissions: 11380
Difficulty: Medium
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)
最直观的思维是:考虑什么情况下没有selfcrossing,由于情况稍微复杂,容易写错且代码冗余。(写的很烂,欢迎优化)
public class Solution {
public boolean isSelfCrossing(int[] x) {
if (x.length <= 3) //判断x长度<=3的情况
return false;
if (x[0] >= x[2] && x[3] >= x[1]) //长度=4时,有没有selfcrossing
return true;
int iIndex = 4;
boolean first = true; //指示是否第一次进入循环,因为第一次进入与后面进入情况不同
while (iIndex < x.length) {
if (first) {
first = false;
if (x[iIndex - 1] < x[iIndex - 3]) { //确定进入“内部循环”的情况
int i = iIndex;
for (; i < x.length; i++) {
if (x[i] >= x[i - 2])
return true;
}
return false;
} else {
if (x[iIndex - 1] == x[iIndex - 3]) {
if (x[iIndex] >= (x[iIndex - 2] - x[iIndex - 4])) //第一次的特殊情况
return true;
else {
for (int i = iIndex + 1; i < x.length; i++) //仍然进入“内部循环”
if (x[i] >= x[i - 2])
return true;
return false;
}
} else {
iIndex++; //超出“内部循环”,重新开始下一个节点
}
}
} else {
if (x[iIndex - 1] <= x[iIndex - 3]) { //不用单独考虑==情况
int i = iIndex;
for (; i < x.length; i++) {
if (i == iIndex) {
if (x[i] >= (x[i - 2] - x[i - 4])&&x[i-1]+x[i-5]>=x[i-3]) //十分容易忽略
return true;
} else {
if (x[i] >= x[i - 2]) //进入“内部循环”
return true;
}
}
return false;
} else {
iIndex++;
}
}
}
return false;
}
}
其实,这道题目如果考虑什么情况会有selfcrossing,就会简单很多。
public class Solution {
public boolean isSelfCrossing(int[] x) {
for(int i=3;i<x.length;i++){
if(i>=3&&x[i]>=x[i-2]&&x[i-1]<=x[i-3])
return true;
if(i>=4&&x[i-1]==x[i-3]&&x[i-2]<=x[i]+x[i-4])
return true;
if(i>=5&&x[i-2]>x[i-4]&&x[i-1]<=x[i-3]&&x[i-1]+x[i-5]>=x[i-3]&&x[i]+x[i-4]>=x[i-2])
return true;
}
return false;
}
}