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)
题目说有一串数x,是一些移动轨迹,从逆时针往北开始走过x[i]长度,说走过的这些轨迹会有相交吗?
一开始以为就四个数,然后判断一波就行了,没想到这里面有坑,x是不定长数组,因此不是走四次就结束了,是要把数组都判断一遍才可以。
对于这个问题,可以这么考虑,分为len(x)<4,len(x)==4,len(x)>4的。
len(x)<4 显然不相交;
len(x)==4, 只有x[2]<=x[0] && x[3]>=x[1]才有可能相交;
len(x)>4时,
我们考虑相交的相反情况,我们找不相交的情况,不相交主要有两种状态,外旋跟内旋,看下图
初始判断进入哪个状态是在x[3]决定,x[3]>x[1]->状态1,x[3]<x[1]->状态2,x[3]==x[1]时比较特殊,要再判断一下x[4]+x[0]>=x[2]是否成立,成立则相交,否则进入状态2。
情况1就是外旋,为了保持外旋的状态,x[i]需要大于x[i-2],由情况3可以看出来,若x[i]<=x[i-2],那么下一个x[i](如果存在),要么变成内旋,要么就相交,所以除非x[i]>x[i-2]能一致保持外旋的状态,否则就要进入中间状态,这里称为状态3。
状态3是为了判断相交或进入状态2而准备的,也就是说在情况3中x[i==6]这步由于x[6]<x[4]所以要进入中间状态了,而且这里要注意根据x[6]的长度,若x[6]+x[2]<x[4]那么下一刻x[7]若相交则只会跟x[4]相交,x[7]必须>x[5],而若x[6]+x[2]>=x[4]那么x[7]+x[3]>x[5]就会导致相交,若不相交,则x[8]开始就会进入状态2。
情况2中,内旋判断x[i]是否会相交只要判断x[i]>x[i-2]成立,就相交。
因此总结起来:
if len(x) <4 then false
if len(x)==4 && x[0] > 0 and x[2] <= x[0] and x[1] > 0 and x[3] >= x[1] then true
if len(x)>5:
当前状态1:若x[i]<=x[i-2]那么根据x[i]长度进入不同的状态3
当前状态2:若x[i]>=x[i-2]=>相交
当前状态3:根据状态3的两种不同情况和x[i]长度判断是相交还是进入状态2
代码如下:
1 class Solution(object): 2 def isSelfCrossing(self, x): 3 """ 4 :type x: List[int] 5 :rtype: bool 6 """ 7 if (len(x) < 4): 8 return False 9 if (x[0] > 0 and x[2] <= x[0] and x[1] > 0 and x[3] >= x[1]): 10 return True 11 if (len(x) < 5): 12 return False 13 statu = 0 14 juage = -1 15 if (x[3] > x[1]): 16 statu = 1 17 if (x[3] < x[1]): 18 statu = 2 19 if (x[3] == x[1]): 20 if(x[4] + x[0]) >= x[2]: 21 return True 22 else: 23 statu = 2 24 for i in range(4, len(x)): 25 if statu == 1: 26 if (x[i] <= x[i - 2]): 27 statu = 0 28 if (x[i - 4] + x[i] >= x[i - 2]): 29 juage = 1 30 continue 31 else: 32 juage = 2 33 continue 34 35 if statu == 2: 36 if (x[i] >= x[i - 2]): 37 return True 38 if juage != -1: 39 if juage == 1: 40 if (x[i] + x[i - 4] < x[i - 2]): 41 statu = 2 42 juage = -1 43 else: 44 return True 45 if juage == 2: 46 if (x[i] < x[i - 2]): 47 statu = 2 48 juage = -1 49 else: 50 return True 51 return False