Skip to content

Commit 86e9d54

Browse files
author
lucifer
committed
feat: #335
1 parent f24fe1e commit 86e9d54

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
261261
- [0239.sliding-window-maximum](./problems/239.sliding-window-maximum.md)
262262
- [0295.find-median-from-data-stream](./problems/295.find-median-from-data-stream.md) 🆕
263263
- [0301.remove-invalid-parentheses](./problems/301.remove-invalid-parentheses.md)
264+
- [0335.self-crossing](./problems/335.self-crossing.md) 🆕
264265
- [0460.lfu-cache](./problems/460.lfu-cache.md) 🆕
265266
- [0493.reverse-pairs](./problems/493.reverse-pairs.md) 🆕
266267
- [1168.optimize-water-distribution-in-a-village](./problems/1168.optimize-water-distribution-in-a-village-cn.md) 🆕

problems/335.self-crossing.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
## 题目地址(335. 路径交叉)
2+
3+
https://leetcode-cn.com/problems/self-crossing/
4+
5+
## 题目描述
6+
7+
```
8+
给定一个含有 n 个正数的数组 x。从点 (0,0) 开始,先向北移动 x[0] 米,然后向西移动 x[1] 米,向南移动 x[2] 米,向东移动 x[3] 米,持续移动。也就是说,每次移动后你的方位会发生逆时针变化。
9+
10+
编写一个 O(1) 空间复杂度的一趟扫描算法,判断你所经过的路径是否相交。
11+
12+
 
13+
14+
示例 1:
15+
16+
┌───┐
17+
│   │
18+
└───┼──>
19+
    │
20+
21+
输入: [2,1,1,2]
22+
输出: true
23+
示例 2:
24+
25+
┌──────┐
26+
│      │
27+
28+
29+
└────────────>
30+
31+
输入: [1,2,3,4]
32+
输出: false
33+
示例 3:
34+
35+
┌───┐
36+
│   │
37+
└───┼>
38+
39+
输入: [1,1,1,1]
40+
输出: true
41+
42+
```
43+
44+
## 思路
45+
46+
符合直觉的做法是$O(N)$时间和空间复杂度的算法。这种算法非常简单,但是题目要求我们使用空间复杂度为$O(1)$的做法。
47+
48+
关于空间复杂度为$O(N)$的算法可以参考我之前的[874.walking-robot-simulation](https://github.com/azl397985856/leetcode/blob/be15d243a3b93d7efa731d0589a54a63cbff61ae/problems/874.walking-robot-simulation.md)。 思路基本是类似,只不过 obstacles(障碍物)不是固定的,而是我们不断遍历的时候动态生成的,我们每遇到一个点,就将其标记为 obstacle。随着算法的进行,我们的 obstacles 逐渐增大,最终和 N 一个量级。
49+
50+
我们考虑进行优化。我们仔细观察发现,如果想让其不相交,从大的范围来看只有两种情况:
51+
52+
1. 我们画的圈不断增大。
53+
2. 我们画的圈不断减少。
54+
55+
![](https://tva1.sinaimg.cn/large/006tNbRwly1gbepb3y3uwj30te1dagn5.jpg)
56+
(有没有感觉像迷宫?)
57+
58+
这样我们会发现,其实我们画最新一笔的时候,并不是之前画的所有的都需要考虑,我们只需要最近的几个就可以了,实际上是最近的五个,不过不知道也没关系,我们稍后会讲解。
59+
60+
![](https://tva1.sinaimg.cn/large/006tNbRwly1gbepcb2ojwj30to0lamxm.jpg)
61+
62+
红色部分指的是我们需要考虑的,而剩余没有被红色标注的部分则无需考虑。不是因为我们无法与之相交,而是我们`一旦与之相交,则必然我们也一定会与红色标记部分相交`
63+
64+
然而我们画的方向也是不用考虑的。比如我当前画的方向是从左到右,那和我画的方向是从上到下有区别么?在这里是没区别的,不信我帮你将上图顺时针旋转 90 度看一下:
65+
66+
![](https://tva1.sinaimg.cn/large/006tNbRwgy1gbepgmzlopj30mk1cwwfn.jpg)
67+
68+
方向对于我们考虑是否相交没有差别。
69+
70+
当我们仔细思考的时候,会发现其实相交的情况只有以下几种:
71+
72+
![](https://tva1.sinaimg.cn/large/006tNbRwly1gbepi1aegtj30ro0o6aat.jpg)
73+
74+
这个时候代码就呼之欲出了。
75+
76+
- 我们只需要遍历数组 x,假设当前是第 i 个元素。
77+
- 如果 x[i] >= x[i - 2] and x[i - 1] <= x[i - 3],则相交(第一种情况)
78+
- 如果 x[i - 1] <= x[i - 3] and x[i - 2] <= x[i],则相交(第二种情况)
79+
- 如果 i > 3 and x[i - 1] == x[i - 3] and x[i] + x[i - 4] == x[i - 2],则相交(第三种情况)
80+
- 如果 i > 4 and x[i] + x[i - 4] >= x[i - 2] and x[i - 1] >= x[i - 3] - x[i - 5] \
81+
and x[i - 1] <= x[i - 3] and x[i - 2] >= x[i - 4] and x[i - 3] >= x[i - 5] ,则相交(第四种情况)
82+
- 否则不相交
83+
84+
## 关键点解析
85+
86+
- 一定要画图辅助
87+
- 对于这种$O(1)$空间复杂度有固定的套路。常见的有:
88+
89+
1. 直接修改原数组
90+
2. 滑动窗口(当前状态并不是和之前所有状态有关,而是仅和某几个有关)。
91+
92+
我们采用的是滑动窗口。但是难点就在于我们怎么知道当前状态和哪几个有关。对于这道题来说,画图或许可以帮助你打开思路。另外面试的时候说出$O(N)$的思路也不失为一个帮助你冷静分析问题的手段。
93+
94+
## 代码
95+
96+
代码支持:Python3
97+
98+
Python3 Code:
99+
100+
```python
101+
class Solution:
102+
def isSelfCrossing(self, x: List[int]) -> bool:
103+
n = len(x)
104+
if n < 4:
105+
return False
106+
for i in range(3, n):
107+
if x[i] >= x[i - 2] and x[i - 1] <= x[i - 3]:
108+
return True
109+
if x[i - 1] <= x[i - 3] and x[i - 2] <= x[i]:
110+
return True
111+
if i > 3 and x[i - 1] == x[i - 3] and x[i] + x[i - 4] == x[i - 2]:
112+
return True
113+
if i > 4 and x[i] + x[i - 4] >= x[i - 2] and x[i - 1] >= x[i - 3] - x[i - 5] \
114+
and x[i - 1] <= x[i - 3] and x[i - 2] >= x[i - 4] and x[i - 3] >= x[i - 5]:
115+
return True
116+
return False
117+
```

0 commit comments

Comments
 (0)