Skip to content

Commit 7b67776

Browse files
committed
【update】专题-双指针
1 parent b10353b commit 7b67776

File tree

1 file changed

+140
-3
lines changed

1 file changed

+140
-3
lines changed

C-算法/专题-B-双指针.md

Lines changed: 140 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
- 双指针问题出现的频率非常高
44
- 九章算法称之为“为面试而生的双指针算法”
55

6-
小结
6+
模板小结
77
---
8-
- 首尾双指针模板
8+
- 首尾双指针
99
- 一般用于寻找数组中满足条件的**两个数**;如果是寻找多个数,则先固定前 n-2 个数
1010
- 为了不遗漏所有可能情况,可能要求数组**有序**
1111
- 遍历时,大于目标时 `hi--`,小于目标时 `lo++`
12-
- 同向双指针模板
12+
- 同向双指针
1313
- 一般用于寻找满足某个条件的**连续区间**
1414
<!-- - 分离双指针
1515
- 输入是两个数组/链表,两个指针分别在两个容器中移动 -->
@@ -33,13 +33,15 @@ Index
3333
- [最小覆盖子串(Minimum Window Substring)](#最小覆盖子串minimum-window-substring)
3434
- [长度最小的子数组(Minimum Size Subarray Sum)](#长度最小的子数组minimum-size-subarray-sum)
3535
- [无重复字符的最长子串(Longest Substring Without Repeating Characters)](#无重复字符的最长子串longest-substring-without-repeating-characters)
36+
- [水果成篮(Fruit Into Baskets)](#水果成篮fruit-into-baskets)
3637
- [其他](#其他)
3738
- [数组中的最长山脉(Longest Mountain in Array)](#数组中的最长山脉longest-mountain-in-array)
3839
- [合并两个有序数组(Merge Sorted Array)](#合并两个有序数组merge-sorted-array)
3940
- [颜色分类(Sort Colors)](#颜色分类sort-colors)
4041
- [两个数组的交集(Intersection of Two Arrays)](#两个数组的交集intersection-of-two-arrays)
4142
- [I](#i)
4243
- [II](#ii)
44+
- [最小区间(Smallest Range)](#最小区间smallest-range)
4345

4446
<!-- /TOC -->
4547

@@ -642,6 +644,7 @@ class Solution:
642644

643645
# 同向双指针
644646

647+
645648
## 最小覆盖子串(Minimum Window Substring)
646649
> LeetCode/76. 最小覆盖子串
647650
@@ -802,6 +805,86 @@ class Solution:
802805
```
803806

804807

808+
## 水果成篮(Fruit Into Baskets)
809+
> LeetCode/[904. 水果成篮](https://leetcode-cn.com/problems/fruit-into-baskets/description/)
810+
811+
**问题描述**
812+
```
813+
在一排树中,第 i 棵树产生 tree[i] 型的水果。
814+
你可以从你选择的任何树开始,然后重复执行以下步骤:
815+
816+
把这棵树上的水果放进你的篮子里。如果你做不到,就停下来。
817+
移动到当前树右侧的下一棵树。如果右边没有树,就停下来。
818+
请注意,在选择一颗树后,你没有任何选择:你必须执行步骤 1,然后执行步骤 2,然后返回步骤 1,然后执行步骤 2,依此类推,直至停止。
819+
820+
你有两个篮子,每个篮子可以携带任何数量的水果,但你希望每个篮子只携带一种类型的水果。
821+
用这个程序你能收集的水果总量是多少?
822+
823+
示例 1:
824+
输入:[1,2,1]
825+
输出:3
826+
解释:我们可以收集 [1,2,1]。
827+
示例 2:
828+
输入:[0,1,2,2]
829+
输出:3
830+
解释:我们可以收集 [1,2,2].
831+
如果我们从第一棵树开始,我们将只能收集到 [0, 1]。
832+
示例 3:
833+
输入:[1,2,3,2,2]
834+
输出:4
835+
解释:我们可以收集 [2,3,2,2].
836+
如果我们从第一棵树开始,我们将只能收集到 [1, 2]。
837+
示例 4:
838+
输入:[3,3,3,1,2,1,1,2,3,3,4]
839+
输出:5
840+
解释:我们可以收集 [1,2,1,1,2].
841+
如果我们从第一棵树或第八棵树开始,我们将只能收集到 4 个水果。
842+
843+
提示:
844+
1 <= tree.length <= 40000
845+
0 <= tree[i] < tree.length
846+
```
847+
848+
**思路**
849+
- 题目大意:寻找一个最大的子区间,该子区间中只包含两种元素(无顺序要求)
850+
- 同向双指针
851+
852+
**Python**
853+
```python
854+
class Solution:
855+
def totalFruit(self, T):
856+
"""
857+
:type T: List[int]
858+
:rtype: int
859+
"""
860+
n = len(T)
861+
862+
l, r = 0, 0
863+
res = 0
864+
q = [] # 模拟容量为 2 的队列
865+
t = dict() # 记录每个种类最后出现的位置
866+
while r < n:
867+
t[T[r]] = r # 更新位置
868+
869+
if T[r] in q and q[-1] == T[r]:
870+
pass
871+
elif T[r] in q and q[0] == T[r]:
872+
q.pop(0)
873+
q.append(T[r])
874+
elif len(q) < 2 and T[r] not in q:
875+
q.append(T[r])
876+
elif len(q) >= 2 and T[r] not in q:
877+
l = t[q.pop(0)] + 1
878+
q.append(T[r])
879+
880+
res = max(res, r - l + 1)
881+
# print(res, '\t', l, r)
882+
r += 1
883+
884+
return res
885+
```
886+
887+
805888
# 其他
806889

807890
## 数组中的最长山脉(Longest Mountain in Array)
@@ -1142,4 +1225,58 @@ class Solution:
11421225
r += 1
11431226

11441227
return res
1228+
```
1229+
1230+
1231+
## 最小区间(Smallest Range)
1232+
> LeetCode/[632. 最小区间](https://leetcode-cn.com/problems/smallest-range/)
1233+
1234+
**问题描述**
1235+
```
1236+
你有 k 个升序排列的整数数组。找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
1237+
1238+
我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。
1239+
1240+
示例 1:
1241+
输入:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
1242+
输出: [20,24]
1243+
解释:
1244+
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
1245+
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
1246+
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。
1247+
注意:
1248+
给定的列表可能包含重复元素,所以在这里升序表示 >= 。
1249+
1 <= k <= 3500
1250+
-10^5 <= 元素的值 <= 10^5
1251+
```
1252+
1253+
**思路**
1254+
- 最小堆
1255+
1256+
**Python**
1257+
- 其中 `l, r` 表示区间;`i, j` 表示 `A[i][j]`
1258+
```python
1259+
import heapq
1260+
1261+
class Solution:
1262+
def smallestRange(self, A):
1263+
"""
1264+
:type A: List[List[int]]
1265+
:rtype: List[int]
1266+
"""
1267+
pq = [(row[0], i, 0) for i, row in enumerate(A)]
1268+
heapq.heapify(pq) # 最小堆
1269+
1270+
ans = -1e5, 1e5
1271+
r = max(row[0] for row in A)
1272+
while pq:
1273+
l, i, j = heapq.heappop(pq)
1274+
if r - l < ans[1] - ans[0]:
1275+
ans = l, r
1276+
if j + 1 == len(A[i]):
1277+
break
1278+
r = max(r, A[i][j+1])
1279+
heapq.heappush(pq, (A[i][j+1], i, j+1))
1280+
1281+
return ans
11451282
```

0 commit comments

Comments
 (0)