原题链接
解析:
本题有目前官方解法只有枚举归纳法,主要的思想是通过列举出所有路径交叉的情况或者不交叉的情况。本博客使用了了列举出不交叉情况的解法,主要是因为本人非常喜欢螺线这个形状,且本题不交叉的情况基本都是螺线型。(本题的路径仅允许逆时针,所以不交叉的路径只可能是螺线型)
阿基米德螺线
不交叉的情况只有三种
1外扩螺线型
即对于任意i>=2.都满足distance[i] > distance[i - 2];
当满足上诉的条件时,路径就会不断的扩张,而不可能出现路线交叉的情形。
2内收螺线型
即当对于任意i>=2(也可以是3).都满足distance[i] < distance[i - 2]
若满足上诉条件,图形就会是一个不断内收的螺线,即和外扩型螺线的方向恰好相反。
3先外扩后内收型
即存在一个j,对于任意i < j 都满足distance[i] > distance[i - 2];
对于任意i > j 都满足distance[i] < distance[i - 2];
着重讲解第三种路径:第三种路径最难理解,想要第三种路径不相交,实际上还存在一个条件:
第三种路径还必须满足在螺线路径内收的过程中,不能和之前的外扩螺线相交。
这是本道题的最难点。
要满足这个条件,必须对某些内收螺线可能和之前的外扩螺线相交的特殊情况进行处理。而外扩和内收螺线可能相交的情形,只有可能有两种。
列举这两种情形之前,
1
i >= 4 && (distance[i] >= distance[i - 2] - distance[i - 4])
以i = 5为例 即第五次移动使得就是外扩螺线和内收螺线的过渡路径,即在这次移动过后路径之后,整体路径就不可能是外扩螺线型了。
只可能有这几种可能:
之后的路径若不是内收型螺线,那就必定出现路径相交。就算是之后的路径的形状是内收型螺线,也无法保证路径必定不相交。
第六次移动必定向左移动,由于假设了第五次移动是是外扩螺线和内收螺线的过渡路径,那么接下来的路径一定是是内收型螺线。很容图看出除了第一种情况不会有相交的危险外,后面三种情况都有相交的危险。
如何处理??
后面的三种情况,使用distance[i - 1] -= distance[i - 3];处理即可。
当 i> 4 时的情况都是类似的,可以自行类推。
2
当i小于4时 先外扩后内收型 只有一种可能会出现相交的情况 那就是
i == 3 && distance[i] == distance[i - 2]
由此已经列举了所有不相交路径的情况,之后只要在代码中体现即可。
源码
class Solution { public boolean isSelfCrossing(int[] distance) { int n = distance.length; int i = 0; //外扩型路径处理 从i=2开始判断即可 while (i < n && (i < 2 || distance[i] > distance[i - 2])) { i++; } if (i == n) return false;//若检查出是外扩螺线路径 及时返回 //出现过渡路径处理 判断两种特殊情况以检测之后的路径和之前的路径发生交叉的情况 if ((i == 3 && distance[i] == distance[i - 2]) || (i >= 4 && (distance[i] >= distance[i - 2] - distance[i - 4]))) { distance[i - 1] -= distance[i - 3]; } i++;//跳过过渡的路径 又因为判断内收螺线路径的成立从4开始检测即可 此语句一举两得 while (i < n && distance[i] < distance[i - 2]) { i++; } return i != n; } }
提交记录