Skip to content

Commit 5ac0fdb

Browse files
author
robot
committed
feat: lc bi-contest-67
1 parent af75b00 commit 5ac0fdb

File tree

4 files changed

+457
-0
lines changed

4 files changed

+457
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ leetcode 题解,记录自己的 leetcode 解题之路。
412412
- [1904. 你完成的完整对局数](./problems/1904.the-number-of-full-rounds-you-have-played.md)
413413
- [1906. 查询差绝对值的最小值](./problems/1906.minimum-absolute-difference-queries.md)
414414
- [2008. 出租车的最大盈利](./problems/2008.maximum-earnings-from-taxi.md)
415+
- [5935. 适合打劫银行的日子](./problems/5935.find-good-days-to-rob-the-bank.md)
416+
- [5936. 引爆最多的炸弹](./problems/5936.detonate-the-maximum-bombs.md)
415417

416418
### 困难难度题目合集
417419

@@ -519,6 +521,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
519521
- [2009. 使数组连续的最少操作数](./problems/2009.minimum-number-of-operations-to-make-array-continuous.md)
520522
- [2025. 分割数组的最多方案数](./problems/2025.maximum-number-of-ways-to-partition-an-array.md)
521523
- [2030. 含特定字母的最小子序列](./problems/2030.smallest-k-length-subsequence-with-occurrences-of-a-letter.md)
524+
- [2102. 序列顺序查询](./problems/2102.sequentially-ordinal-rank-tracker.md)
522525

523526
## :trident:  anki 卡片
524527

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
## 题目地址(2102. 序列顺序查询)
2+
3+
https://leetcode-cn.com/problems/21/
4+
5+
## 题目描述
6+
7+
```
8+
一个观光景点由它的名字 name 和景点评分 score 组成,其中 name 是所有观光景点中 唯一 的字符串,score 是一个整数。景点按照最好到最坏排序。景点评分 越高 ,这个景点越好。如果有两个景点的评分一样,那么 字典序较小 的景点更好。
9+
10+
你需要搭建一个系统,查询景点的排名。初始时系统里没有任何景点。这个系统支持:
11+
12+
添加 景点,每次添加 一个 景点。
13+
查询 已经添加景点中第 i 好 的景点,其中 i 是系统目前位置查询的次数(包括当前这一次)。
14+
比方说,如果系统正在进行第 4 次查询,那么需要返回所有已经添加景点中第 4 好的。
15+
16+
注意,测试数据保证 任意查询时刻 ,查询次数都 不超过 系统中景点的数目。
17+
18+
请你实现 SORTracker 类:
19+
20+
SORTracker() 初始化系统。
21+
void add(string name, int score) 向系统中添加一个名为 name 评分为 score 的景点。
22+
string get() 查询第 i 好的景点,其中 i 是目前系统查询的次数(包括当前这次查询)。
23+
24+
 
25+
26+
示例:
27+
28+
输入:
29+
["SORTracker", "add", "add", "get", "add", "get", "add", "get", "add", "get", "add", "get", "get"]
30+
[[], ["bradford", 2], ["branford", 3], [], ["alps", 2], [], ["orland", 2], [], ["orlando", 3], [], ["alpine", 2], [], []]
31+
输出:
32+
[null, null, null, "branford", null, "alps", null, "bradford", null, "bradford", null, "bradford", "orland"]
33+
34+
解释:
35+
SORTracker tracker = new SORTracker(); // 初始化系统
36+
tracker.add("bradford", 2); // 添加 name="bradford" 且 score=2 的景点。
37+
tracker.add("branford", 3); // 添加 name="branford" 且 score=3 的景点。
38+
tracker.get(); // 从好带坏的景点为:branford ,bradford 。
39+
// 注意到 branford 比 bradford 好,因为它的 评分更高 (3 > 2) 。
40+
// 这是第 1 次调用 get() ,所以返回最好的景点:"branford" 。
41+
tracker.add("alps", 2); // 添加 name="alps" 且 score=2 的景点。
42+
tracker.get(); // 从好到坏的景点为:branford, alps, bradford 。
43+
// 注意 alps 比 bradford 好,虽然它们评分相同,都为 2 。
44+
// 这是因为 "alps" 字典序 比 "bradford" 小。
45+
// 返回第 2 好的地点 "alps" ,因为当前为第 2 次调用 get() 。
46+
tracker.add("orland", 2); // 添加 name="orland" 且 score=2 的景点。
47+
tracker.get(); // 从好到坏的景点为:branford, alps, bradford, orland 。
48+
// 返回 "bradford" ,因为当前为第 3 次调用 get() 。
49+
tracker.add("orlando", 3); // 添加 name="orlando" 且 score=3 的景点。
50+
tracker.get(); // 从好到坏的景点为:branford, orlando, alps, bradford, orland 。
51+
// 返回 "bradford".
52+
tracker.add("alpine", 2); // 添加 name="alpine" 且 score=2 的景点。
53+
tracker.get(); // 从好到坏的景点为:branford, orlando, alpine, alps, bradford, orland 。
54+
// 返回 "bradford" 。
55+
tracker.get(); // 从好到坏的景点为:branford, orlando, alpine, alps, bradford, orland 。
56+
// 返回 "orland" 。
57+
58+
59+
 
60+
61+
提示:
62+
63+
name 只包含小写英文字母,且每个景点名字互不相同。
64+
1 <= name.length <= 10
65+
1 <= score <= 105
66+
任意时刻,调用 get 的次数都不超过调用 add 的次数。
67+
总共 调用 add 和 get 不超过 4 * 104 
68+
```
69+
70+
## 前置知识
71+
72+
- 平衡二叉树
73+
74+
## 公司
75+
76+
- 暂无
77+
78+
## 思路
79+
80+
这种题目适合使用平衡二叉树来做。如果对其不熟悉,可以参考我的二分专题。
81+
82+
另外这种动态求极值的,也可以考虑使用堆。不过我们求的是 第 k 大,而不是最大。因此可使用堆中的固定堆技巧来实现。具体可以参考我的堆专题。
83+
84+
想到使用平衡二叉树后,思路就简单了。 一开始我的想法是:
85+
86+
```py
87+
88+
from sortedcontainers import SortedList
89+
class SORTracker:
90+
91+
def __init__(self):
92+
sl = SortedList()
93+
self.i = -1
94+
self.sl = sl
95+
96+
def add(self, name: str, score: int) -> None:
97+
self.sl.add((score, name))
98+
99+
def get(self) -> str:
100+
ans = self.sl[self.i][1]
101+
self.i += 1
102+
return ans
103+
```
104+
105+
不过这是不对的。
106+
107+
这是因为题目约定了**如果有两个景点的评分一样,那么 字典序较小   的景点更好**
108+
109+
而上面的代码会返回字典序较大的。一种简单的想法是 add 的时候将 name 取反放进去。由于字符串不能直接取反,我们需要先想办法把他们转为数字进行处理。代码如下
110+
111+
```py
112+
113+
from sortedcontainers import SortedList
114+
class SORTracker:
115+
116+
def __init__(self):
117+
sl = SortedList()
118+
self.i = -1
119+
self.sl = sl
120+
121+
def add(self, name: str, score: int) -> None:
122+
self.sl.add((score, -1 * toNumber(name) ,name))
123+
124+
def get(self) -> str:
125+
ans = self.sl[self.i][2]
126+
self.i += 1
127+
return ans
128+
```
129+
130+
实际上一种更简单的方法是 add 的时候对 score 进行取反,接下来 get 的时候从另外一头取即可。 具体见下方代码。
131+
132+
## 关键点
133+
134+
- add 的时候对 score 取反,达到**如果有两个景点的评分一样,那么 字典序较小   的景点更好**的效果。
135+
136+
## 代码
137+
138+
- 语言支持:Python3
139+
140+
Python3 Code:
141+
142+
```python
143+
144+
from sortedcontainers import SortedList
145+
class SORTracker:
146+
147+
def __init__(self):
148+
sl = SortedList()
149+
self.i = 0
150+
self.sl = sl
151+
152+
def add(self, name: str, score: int) -> None:
153+
self.sl.add((-score, name))
154+
155+
def get(self) -> str:
156+
ans = self.sl[self.i][1]
157+
self.i += 1
158+
return ans
159+
160+
161+
162+
# Your SORTracker object will be instantiated and called as such:
163+
# obj = SORTracker()
164+
# obj.add(name,score)
165+
# param_2 = obj.get()
166+
167+
```
168+
169+
**复杂度分析**
170+
171+
令 n 为数组长度。
172+
173+
- 时间复杂度:$O(logn)$
174+
- 空间复杂度:$O(n)$
175+
176+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
177+
178+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
179+
180+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
181+
182+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
183+
184+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
## 题目地址(5935. 适合打劫银行的日子)
2+
3+
https://leetcode-cn.com/problems/find-good-days-to-rob-the-bank/
4+
5+
## 题目描述
6+
7+
```
8+
你和一群强盗准备打劫银行。给你一个下标从 0 开始的整数数组 security ,其中 security[i] 是第 i 天执勤警卫的数量。日子从 0 开始编号。同时给你一个整数 time 。
9+
10+
如果第 i 天满足以下所有条件,我们称它为一个适合打劫银行的日子:
11+
12+
第 i 天前和后都分别至少有 time 天。
13+
第 i 天前连续 time 天警卫数目都是非递增的。
14+
第 i 天后连续 time 天警卫数目都是非递减的。
15+
16+
更正式的,第 i 天是一个合适打劫银行的日子当且仅当:security[i - time] >= security[i - time + 1] >= ... >= security[i] <= ... <= security[i + time - 1] <= security[i + time].
17+
18+
请你返回一个数组,包含 所有 适合打劫银行的日子(下标从 0 开始)。返回的日子可以 任意 顺序排列。
19+
20+
 
21+
22+
示例 1:
23+
24+
输入:security = [5,3,3,3,5,6,2], time = 2
25+
输出:[2,3]
26+
解释:
27+
第 2 天,我们有 security[0] >= security[1] >= security[2] <= security[3] <= security[4] 。
28+
第 3 天,我们有 security[1] >= security[2] >= security[3] <= security[4] <= security[5] 。
29+
没有其他日子符合这个条件,所以日子 2 和 3 是适合打劫银行的日子。
30+
31+
32+
示例 2:
33+
34+
输入:security = [1,1,1,1,1], time = 0
35+
输出:[0,1,2,3,4]
36+
解释:
37+
因为 time 等于 0 ,所以每一天都是适合打劫银行的日子,所以返回每一天。
38+
39+
40+
示例 3:
41+
42+
输入:security = [1,2,3,4,5,6], time = 2
43+
输出:[]
44+
解释:
45+
没有任何一天的前 2 天警卫数目是非递增的。
46+
所以没有适合打劫银行的日子,返回空数组。
47+
48+
49+
示例 4:
50+
51+
输入:security = [1], time = 5
52+
输出:[]
53+
解释:
54+
没有日子前面和后面有 5 天时间。
55+
所以没有适合打劫银行的日子,返回空数组。
56+
57+
 
58+
59+
提示:
60+
61+
1 <= security.length <= 105
62+
0 <= security[i], time <= 105
63+
```
64+
65+
## 前置知识
66+
67+
- 动态规划
68+
69+
## 公司
70+
71+
- 暂无
72+
73+
## 思路
74+
75+
对于每一个位置 i ,我们如何判断其是否适合打劫呢?显然我们需要知道:
76+
77+
1. i 前面有多少小于等于当前位置的连续位置个数。
78+
2. i 后面有多少大于等于当前位置的连续位置个数。
79+
80+
因此我们可以先进行一次预处理,将上面的两个信息求出来。不妨使用两个数组 l 和 r 分别存储。比如 l[i] 表示 i 左侧有多少个连续位置是小于等于 security[i] 的。
81+
82+
接下来我们只需要遍历一次 security 就可以判断出每一个位置是否适合打劫。如果适合打劫就加入到结果数组 ans 中。
83+
84+
## 关键点
85+
86+
- 预处理出数组 l 和 r
87+
88+
## 代码
89+
90+
- 语言支持:Python3
91+
92+
Python3 Code:
93+
94+
```python
95+
96+
class Solution:
97+
def goodDaysToRobBank(self, security: List[int], time: int) -> List[int]:
98+
n = len(security)
99+
l, r = [0]*n, [0]*n
100+
ans = []
101+
102+
for i in range(1, n):
103+
if security[i] <= security[i-1]:
104+
l[i] += l[i-1] + 1
105+
for i in range(n-2,-1,-1):
106+
if security[i] <= security[i+1]:
107+
r[i] += r[i+1] + 1
108+
109+
for i in range(n):
110+
if l[i] >= time and r[i] >= time:
111+
ans.append(i)
112+
return ans
113+
114+
```
115+
116+
**复杂度分析**
117+
118+
令 n 为数组长度。
119+
120+
- 时间复杂度:$O(n)$
121+
- 空间复杂度:$O(n)$
122+
123+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
124+
125+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
126+
127+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
128+
129+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
130+
131+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)

0 commit comments

Comments
 (0)