LeetCode 335. Self Crossing

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)


首先这道题主要求的就是

给定一个包含n个正整数的数组x。从(0, 0)点出发先向北移动x[0]米,然后向西移动x[1]米,再向南移动x[2]米,再向东移动x[3]米,以此类推。换言之,每一次移动之后都逆时针旋转一次方向。

编写一个算法,并且只使用O(1)的额外空间来确定路径是否自相交。


一开始我的思路就是错的,我想的是使用坐标的思想解决问题,使用x、y轴正负求解,但是很明显我错了,这道题不可能这么简单!

那就要仔细思考这道题怎么解决,我又有了两个思路:

第一个思路:反向推导

既然求自交那我就求不交来反证,那么不交的情况就有三种:

1.螺旋自增2.螺旋自减3.螺旋自增然后再螺旋自减

想的很清楚,可是编程很困难,前两条很容易实现就是比大小,但是怎么个判断第三条呢?

在写这篇文章的时候有了思路,就是自增和自减的区别就是要比较大小不同,

自增是 在四条线循环中,第一条线小于第三条线,同时第二条线小于第四条线

自减是 在四条线循环中,第一条线大于第三条线,同时第二条线大于第四条线

这就可以明确确定出什么时候是自增后再自减,在这种情况下呢,就要做一个判断自增再自减不会相互交,那么也就是说有两种情况:

LeetCode <wbr>335. <wbr>Self <wbr>Crossing

可以看出只有这两种情况可以保证其彼此不自交,也就是

左图中:

a》c+f&&d《g&&a》f

右图中:

b》d+g&&a》f&&h《c

这就能保证其不会自交,但是在编程过程中思考为什么不去判断其自交从而可以直接中断程序运行,让程序更迅速呢?

这就是第二种思路的诞生——判断自交

怎么判断自交呢?这就得分类了,但是每四条边作为一组数据看待,这没得说了

一般就可以分成两类,第一类就是在这个四边组内自交,第二个就是这个四边组和上一个四边组相交。

第一,四边组内自相交:也就是第四条边正好和第一条边相交。

第二,两个四边组相交:其实在一开始的思路上就可以发现第一三两条边是在同一个轴,二四两条边在另一个轴,这都是可以相互比较的。

接下来就是讨论了:

假设已经有了0,1.2、3四条不相交的边,那么

再加一条边相交就是 4》=2&&3《=1或者就是4+0》=2&&1==3

再加两条边:5+1》=3&&4《=2&&4+0》=2&&1《=3

以此类推;

但是结果依旧失败,没有考虑到一些情况,这里面就是没有考虑到其实应该按照每四条边依次组成组合也就是:(1234)(2345)等等

根据niwota大神的帖子,总算是明白自己欠缺的部分了
      for(int i=3, l=x.size(); i
           // Case 1: current line crosses the line 3 steps ahead of it
           if(x[i]>=x[i-2] && x[i-1]<=x[i-3]) returntrue; 
           // Case 2: current line crosses the line 4 steps ahead of it
           else if(i>=4 && x[i-1]==x[i-3] &&x[i]+x[i-4]>=x[i-2]) return true;
           // Case 3: current line crosses the line 6 steps ahead of it
           else if(i>=5 && x[i-2]>=x[i-4] &&x[i]+x[i-4]>=x[i-2] && x[i-1]<=x[i-3] &&x[i-1]+x[i-5]>=x[i-3]) return true; 
       }
       return false;
   }

 

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值