路径交叉,有点难度
Posted Roam-G
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了路径交叉,有点难度相关的知识,希望对你有一定的参考价值。
难度困难104
给你一个整数数组 distance
。
从 X-Y 平面上的点 (0,0)
开始,先向北移动 distance[0]
米,然后向西移动 distance[1]
米,向南移动 distance[2]
米,向东移动 distance[3]
米,持续移动。也就是说,每次移动后你的方位会发生逆时针变化。
判断你所经过的路径是否相交。如果相交,返回 true
;否则,返回 false
。
示例 1:
输入:distance = [2,1,1,2] 输出:true
示例 2:
输入:distance = [1,2,3,4] 输出:false
示例 3:
输入:distance = [1,1,1,1] 输出:true
提示:
1 <= distance.length <= 105
1 <= distance[i] <= 105
通过次数8,755提交次数21,108
我们先通过枚举各种移动方案来归纳路径交叉的规律。
第 11 次移动和第 22 次移动的情况:
因为这两次移动都是各自方向上的第一次移动,所以这两次移动距离将作为之后移动距离的参考系,但本身没有意义。因此,此时只有 2-12−1 一种情况。
第 33 次移动的情况:
此时一定是 2-12−1,第 33 次移动距离相较于第 11 次移动距离,有三种情况:
3-13−1:第 33 次移动距离小于第 11 次移动距离;
3-23−2:第 33 次移动距离等于第 11 次移动距离;
3-33−3:第 33 次移动距离大于第 11 次移动距离。
第 44 次移动的情况:
当前 33 次移动是 3-13−1 时,第 44 次移动距离相较于第 22 次移动距离,有两种情况:
4-14−1:第 44 次移动距离小于第 22 次移动距离;
4-24−2 和 4-34−3:第 44 次移动距离大于等于第 22 次移动距离相同,出现路径交叉。
根据以上结果,我们发现 3-13−1 具有如下性质:如果在当前的第 ii 次移动之后,存在第 jj 次移动(j > ij>i)的距离大于等于第 j-2j−2 次移动的距离,则会出现路径交叉。另外,我们发现 4-14−1 具有和 3-13−1 相同的性质,于是 4-14−1 等价于 3-13−1;不需要继续讨论 4-14−1 的后续情况。
当前 33 次移动是 3-23−2 时,第 44 次移动距离相较于第 22 次移动距离,有两种情况:
4-44−4:第 44 次移动距离小于第 22 次移动距离;
4-54−5 和 4-64−6:第 44 次移动距离大于等于第 22 次移动距离,出现路径交叉。
根据以上结果,我们发现 3-23−2 具有和 3-13−1 相同的性质,于是 4-44−4 等价于 3-23−2,并间接地等价于 3-13−1;不需要继续讨论 4-44−4 的后续情况。
当前 33 次移动是 3-33−3 时,第 44 次移动距离相较于第 22 次移动距离,有三种情况:
4-74−7:第 44 次移动距离小于第 22 次移动距离;
4-84−8:第 44 次移动距离等于第 22 次移动距离;
4-94−9:第 44 次移动距离大于第 22 次移动距离。
根据以上结果,我们发现 4-74−7 也具有和 3-13−1 相同的性质,于是 4-74−7 等价于 3-13−1;不需要继续讨论 4-74−7 的后续情况。
第 55 次移动的情况:
此时还需要讨论前 44 次移动是 4-84−8 或 4-94−9 的情况。
当前 44 次移动是 4-84−8 时,第 55 次移动距离相较于第 33 次移动距离和第 11 次移动距离,有两种情况:
5-15−1:第 55 次移动距离小于第 33 次移动距离减第 11 次移动距离的差;
5-25−2 和 5-35−3:第 55 次移动距离大于等于第 33 次移动距离减第 11 次移动距离的差,出现路径交叉。
根据以上结果,我们发现 5-15−1 也具有和 3-13−1 相同的性质,于是 5-15−1 等价于 3-13−1;不需要继续讨论 5-15−1 的后续情况。
当前 44 次移动是 4-94−9 时,第 55 次移动距离相较于第 33 次移动距离和第 11 次移动距离,有三种情况:
5-45−4:第 55 次移动距离小于第 33 次移动距离减第 11 次移动距离的差;
5-55−5、5-65−6 和 5-75−7:第 55 次移动距离大于等于第 33 次移动距离减第 11 次移动距离的差,且小于等于第 33 次移动距离;
5-85−8:第 55 次移动距离大于第 33 次移动距离。
根据以上结果,我们发现 5-45−4 也具有和 3-13−1 相同的性质,于是 5-15−1 等价于 3-13−1;不需要继续讨论 5-45−4 的后续情况。
第 66 次移动的情况:
此时还需要讨论前 55 次移动是 5-55−5、5-65−6 或 5-75−7 的情况,以及前 55 次移动是 5-85−8 的情况。
当前 55 次移动是 5-55−5、5-65−6 或 5-75−7 时,我们不妨以 5-65−6 为例,第 66 次移动距离相较于第 44 次移动距离和第 22 次移动距离,有两种情况:
6-16−1:第 66 次移动距离小于第 44 次移动距离减第 22 次移动距离的差;
6-26−2 和 6-36−3:第 66 次移动距离大于等于第 44 次移动距离减第 22 次移动距离的差,出现路径交叉。
根据以上结果,我们发现 6-16−1 也具有和 3-13−1 相同的性质,于是 6-16−1 等价于 3-13−1;不需要继续讨论 6-16−1 的后续情况。
当前 55 次移动是 5-85−8 时,第 66 次移动距离相较于第 44 次移动距离和第 22 次移动距离,有三种情况:
6-46−4:第 66 次移动距离小于第 44 次移动距离减第 22 次移动距离的差;
6-56−5、6-66−6 和 6-76−7:第 66 次移动距离大于等于第 44 次移动距离减第 22 次移动距离的差,且小于等于第 44 次移动距离;
6-86−8:第 66 次移动距离大于第 44 次移动距离。
根据以上结果,我们发现 6-46−4 与 5-45−4 的情况类似,都具有 3-13−1 的性质;6-56−5、6-66−6、6-76−7 与 5-55−5、5-65−6、5-75−7 的情况类似,后续可能出现的情况类似于 6-16−1、6-26−2 和 6-36−3;6-86−8 与 5-85−8 的情况类似,后续可能出现的情况类似 6-46−4、6-56−5、6-66−6、6-76−7 和 6-86−8。
至此,我们已经通过归纳基本得到了路径交叉的规律。
方法一:归纳法(归纳路径交叉的情况)
思路和算法
根据归纳结果,我们发现所有可能的路径交叉的情况只有以下三类:
第 11 类,如上图所示,第 ii 次移动和第 i-3i−3 次移动(包含端点)交叉的情况,例如归纳中的 4-24−2、4-34−3、4-54−5 和 4-64−6。
这种路径交叉需满足以下条件:
第 i-1i−1 次移动距离小于等于第 i-3i−3 次移动距离。
第 ii 次移动距离大于等于第 i-2i−2 次移动距离。
第 22 类,如上图所示,第 55 次移动和第 11 次移动交叉(重叠)的情况,例如归纳中的 5-25−2 和 5-35−3。这类路径交叉的情况实际上是第 33 类路径交叉在边界条件下的一种特殊情况。
这种路径交叉需要满足以下条件:
第 44 次移动距离等于第 22 次移动距离。
第 55 次移动距离大于等于第 33 次移动距离减第 11 次移动距离的差;注意此时第 33 次移动距离一定大于第 11 次移动距离,否则在上一步就已经出现第 11 类路径交叉的情况了。
第 33 类,如上图所示,第 ii 次移动和第 i-5i−5 次移动(包含端点)交叉的情况,例如归纳中的 6-26−2 和 6-36−3。
这种路径交叉需满足以下条件:
第 i-1i−1 次移动距离大于等于第 i-3i−3 次移动距离减第 i-5i−5 次移动距离的差,且小于等于第 i-3i−3 次移动距离;注意此时第 i-3i−3 次移动距离一定大于第 i-5i−5 次移动距离,否则在两步之前就已经出现第 11 类路径交叉的情况了。
第 i-2i−2 次移动距离大于第 i-4i−4 次移动距离;注意此时第 i-2i−2 次移动距离一定不等于第 i-4i−4 次移动距离,否则在上一步就会出现第 33 类路径交叉(或第 22 类路径交叉)的情况了。
第 ii 次移动距离大于等于第 i-2i−2 次移动距离减第 i-4i−4 次移动距离的差。
class Solution {
public:
bool isSelfCrossing(vector<int>& distance) {
int n = distance.size();
for (int i = 3; i < n; ++i) {
// 第 1 类路径交叉的情况
if (distance[i] >= distance[i - 2] && distance[i - 1] <= distance[i - 3]) {
return true;
}
// 第 2 类路径交叉的情况
if (i == 4 && (distance[3] == distance[1]
&& distance[4] >= distance[2] - distance[0])) {
return true;
}
// 第 3 类路径交叉的情况
if (i >= 5 && (distance[i - 3] - distance[i - 5] <= distance[i - 1]
&& distance[i - 1] <= distance[i - 3]
&& distance[i] >= distance[i - 2] - distance[i - 4]
&& distance[i - 2] > distance[i - 4])) {
return true;
}
}
return false;
}
};
java
class Solution {
public boolean isSelfCrossing(int[] distance) {
int n = distance.length;
for (int i = 3; i < n; ++i) {
// 第 1 类路径交叉的情况
if (distance[i] >= distance[i - 2] && distance[i - 1] <= distance[i - 3]) {
return true;
}
// 第 2 类路径交叉的情况
if (i == 4 && (distance[3] == distance[1]
&& distance[4] >= distance[2] - distance[0])) {
return true;
}
// 第 3 类路径交叉的情况
if (i >= 5 && (distance[i - 3] - distance[i - 5] <= distance[i - 1]
&& distance[i - 1] <= distance[i - 3]
&& distance[i] >= distance[i - 2] - distance[i - 4]
&& distance[i - 2] > distance[i - 4])) {
return true;
}
}
return false;
}
}
Python
class Solution:
def isSelfCrossing(self, distance: List[int]) -> bool:
n = len(distance)
for i in range(3, n):
# 第 1 类路径交叉的情况
if (distance[i] >= distance[i - 2]
and distance[i - 1] <= distance[i - 3]):
return True
# 第 2 类路径交叉的情况
if i == 4 and (distance[3] == distance[1]
and distance[4] >= distance[2] - distance[0]):
return True
# 第 3 类路径交叉的情况
if i >= 5 and (distance[i - 3] - distance[i - 5] <= distance[i - 1] <= distance[i - 3]
and distance[i] >= distance[i - 2] - distance[i - 4]
and distance[i - 2] > distance[i - 4]):
return True
return False
以上是关于路径交叉,有点难度的主要内容,如果未能解决你的问题,请参考以下文章