[leetcode]335. Self Crossing

Posted on 2017-07-04 15:50  你猜我猜不猜你猜不猜  阅读(274)  评论(0)    收藏  举报
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

 

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3