Skip to content

Commit ac3a248

Browse files
authored
feat: add solutions to lcci problem: No.17.18 (#1214)
No.17.18.Shortest Supersequence
1 parent 33c2e82 commit ac3a248

File tree

7 files changed

+446
-2
lines changed

7 files changed

+446
-2
lines changed

lcci/17.18.Shortest Supersequence/README.md

+160-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
## 题目描述
66

77
<!-- 这里写题目描述 -->
8+
89
<p>假设你有两个数组,一个长一个短,短的元素均不相同。找到长数组中包含短数组所有的元素的最短子数组,其出现顺序无关紧要。</p>
910
<p>返回最短子数组的左端点和右端点,如有多个满足条件的子数组,返回左端点最小的一个。若不存在,返回空数组。</p>
1011
<p><strong>示例 1:</strong></p>
@@ -26,22 +27,180 @@ small = [4]
2627
## 解法
2728

2829
<!-- 这里可写通用的实现逻辑 -->
30+
31+
**方法一:哈希表 + 双指针**
32+
33+
我们定义两个哈希表,其中哈希表 $need$ 用于存储数组 $small$ 中的元素及其出现次数,哈希表 $window$ 用于存储当前滑动窗口中的元素及其出现次数。另外,我们用变量 $cnt$ 记录当前未满足条件的元素个数,用变量 $mi$ 记录最短子数组的长度,用变量 $k$ 记录最短子数组的左端点。
34+
35+
我们用双指针 $j$ 和 $i$ 分别表示滑动窗口的左右端点,初始时,$j$ 和 $i$ 均指向数组 $big$ 的第一个元素。我们先移动右指针 $i$,将 $big[i]$ 加入到 $window$ 中,如果 $window[big[i]]$ 的值小于等于 $need[big[i]]$ 的值,说明当前滑动窗口中包含数组 $small$ 中的一个元素,令 $cnt$ 减一。当 $cnt$ 的值等于 $0$ 时,说明当前滑动窗口中包含数组 $small$ 中的所有元素,此时我们移动左指针 $j$,将 $big[j]$ 从 $window$ 中减去,如果 $window[big[j]]$ 的值小于 $need[big[j]]$ 的值,说明当前滑动窗口不再包含数组 $small$ 中的所有元素,令 $cnt$ 加一。在滑动窗口移动的过程中,我们更新 $mi$ 和 $k$ 的值。
36+
37+
时间复杂度 $O(m + n)$,空间复杂度 $O(m + n)$。其中 $m$ 和 $n$ 分别是数组 $big$ 和 $small$ 的长度。
38+
2939
<!-- tabs:start -->
3040

3141
### **Python3**
3242

3343
<!-- 这里可写当前语言的特殊实现逻辑 -->
3444

3545
```python
36-
46+
class Solution:
47+
def shortestSeq(self, big: List[int], small: List[int]) -> List[int]:
48+
need = Counter(small)
49+
window = Counter()
50+
cnt, j, k, mi = len(small), 0, -1, inf
51+
for i, x in enumerate(big):
52+
window[x] += 1
53+
if need[x] >= window[x]:
54+
cnt -= 1
55+
while cnt == 0:
56+
if i - j + 1 < mi:
57+
mi = i - j + 1
58+
k = j
59+
if need[big[j]] >= window[big[j]]:
60+
cnt += 1
61+
window[big[j]] -= 1
62+
j += 1
63+
return [] if k < 0 else [k, k + mi - 1]
3764
```
3865

3966
### **Java**
4067

4168
<!-- 这里可写当前语言的特殊实现逻辑 -->
4269

4370
```java
71+
class Solution {
72+
public int[] shortestSeq(int[] big, int[] small) {
73+
int cnt = small.length;
74+
Map<Integer, Integer> need = new HashMap<>(cnt);
75+
Map<Integer, Integer> window = new HashMap<>(cnt);
76+
for (int x : small) {
77+
need.put(x, 1);
78+
}
79+
int k = -1, mi = 1 << 30;
80+
for (int i = 0, j = 0; i < big.length; ++i) {
81+
window.merge(big[i], 1, Integer::sum);
82+
if (need.getOrDefault(big[i], 0) >= window.get(big[i])) {
83+
--cnt;
84+
}
85+
while (cnt == 0) {
86+
if (i - j + 1 < mi) {
87+
mi = i - j + 1;
88+
k = j;
89+
}
90+
if (need.getOrDefault(big[j], 0) >= window.get(big[j])) {
91+
++cnt;
92+
}
93+
window.merge(big[j++], -1, Integer::sum);
94+
}
95+
}
96+
return k < 0 ? new int[0] : new int[] {k, k + mi - 1};
97+
}
98+
}
99+
```
100+
101+
### **C++**
102+
103+
```cpp
104+
class Solution {
105+
public:
106+
vector<int> shortestSeq(vector<int>& big, vector<int>& small) {
107+
int cnt = small.size();
108+
unordered_map<int, int> need;
109+
unordered_map<int, int> window;
110+
for (int x : small) {
111+
need[x] = 1;
112+
}
113+
int k = -1, mi = 1 << 30;
114+
for (int i = 0, j = 0; i < big.size(); ++i) {
115+
window[big[i]]++;
116+
if (need[big[i]] >= window[big[i]]) {
117+
--cnt;
118+
}
119+
while (cnt == 0) {
120+
if (i - j + 1 < mi) {
121+
mi = i - j + 1;
122+
k = j;
123+
}
124+
if (need[big[j]] >= window[big[j]]) {
125+
++cnt;
126+
}
127+
window[big[j++]]--;
128+
}
129+
}
130+
if (k < 0) {
131+
return {};
132+
}
133+
return {k, k + mi - 1};
134+
}
135+
};
136+
```
137+
138+
### **Go**
139+
140+
```go
141+
func shortestSeq(big []int, small []int) []int {
142+
cnt := len(small)
143+
need := map[int]int{}
144+
window := map[int]int{}
145+
for _, x := range small {
146+
need[x] = 1
147+
}
148+
j, k, mi := 0, -1, 1<<30
149+
for i, x := range big {
150+
window[x]++
151+
if need[x] >= window[x] {
152+
cnt--
153+
}
154+
for cnt == 0 {
155+
if t := i - j + 1; t < mi {
156+
mi = t
157+
k = j
158+
}
159+
if need[big[j]] >= window[big[j]] {
160+
cnt++
161+
}
162+
window[big[j]]--
163+
j++
164+
}
165+
}
166+
if k < 0 {
167+
return []int{}
168+
}
169+
return []int{k, k + mi - 1}
170+
}
171+
```
44172

173+
### **TypeScript**
174+
175+
```ts
176+
function shortestSeq(big: number[], small: number[]): number[] {
177+
let cnt = small.length;
178+
const need: Map<number, number> = new Map();
179+
const window: Map<number, number> = new Map();
180+
for (const x of small) {
181+
need.set(x, 1);
182+
}
183+
let k = -1;
184+
let mi = 1 << 30;
185+
for (let i = 0, j = 0; i < big.length; ++i) {
186+
window.set(big[i], (window.get(big[i]) ?? 0) + 1);
187+
if ((need.get(big[i]) ?? 0) >= window.get(big[i])!) {
188+
--cnt;
189+
}
190+
while (cnt === 0) {
191+
if (i - j + 1 < mi) {
192+
mi = i - j + 1;
193+
k = j;
194+
}
195+
if ((need.get(big[j]) ?? 0) >= window.get(big[j])!) {
196+
++cnt;
197+
}
198+
window.set(big[j], window.get(big[j])! - 1);
199+
++j;
200+
}
201+
}
202+
return k < 0 ? [] : [k, k + mi - 1];
203+
}
45204
```
46205

47206
### **...**

lcci/17.18.Shortest Supersequence/README_EN.md

+150-1
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,162 @@ small = [4]
4141
### **Python3**
4242

4343
```python
44-
44+
class Solution:
45+
def shortestSeq(self, big: List[int], small: List[int]) -> List[int]:
46+
need = Counter(small)
47+
window = Counter()
48+
cnt, j, k, mi = len(small), 0, -1, inf
49+
for i, x in enumerate(big):
50+
window[x] += 1
51+
if need[x] >= window[x]:
52+
cnt -= 1
53+
while cnt == 0:
54+
if i - j + 1 < mi:
55+
mi = i - j + 1
56+
k = j
57+
if need[big[j]] >= window[big[j]]:
58+
cnt += 1
59+
window[big[j]] -= 1
60+
j += 1
61+
return [] if k < 0 else [k, k + mi - 1]
4562
```
4663

4764
### **Java**
4865

4966
```java
67+
class Solution {
68+
public int[] shortestSeq(int[] big, int[] small) {
69+
int cnt = small.length;
70+
Map<Integer, Integer> need = new HashMap<>(cnt);
71+
Map<Integer, Integer> window = new HashMap<>(cnt);
72+
for (int x : small) {
73+
need.put(x, 1);
74+
}
75+
int k = -1, mi = 1 << 30;
76+
for (int i = 0, j = 0; i < big.length; ++i) {
77+
window.merge(big[i], 1, Integer::sum);
78+
if (need.getOrDefault(big[i], 0) >= window.get(big[i])) {
79+
--cnt;
80+
}
81+
while (cnt == 0) {
82+
if (i - j + 1 < mi) {
83+
mi = i - j + 1;
84+
k = j;
85+
}
86+
if (need.getOrDefault(big[j], 0) >= window.get(big[j])) {
87+
++cnt;
88+
}
89+
window.merge(big[j++], -1, Integer::sum);
90+
}
91+
}
92+
return k < 0 ? new int[0] : new int[] {k, k + mi - 1};
93+
}
94+
}
95+
```
96+
97+
### **C++**
98+
99+
```cpp
100+
class Solution {
101+
public:
102+
vector<int> shortestSeq(vector<int>& big, vector<int>& small) {
103+
int cnt = small.size();
104+
unordered_map<int, int> need;
105+
unordered_map<int, int> window;
106+
for (int x : small) {
107+
need[x] = 1;
108+
}
109+
int k = -1, mi = 1 << 30;
110+
for (int i = 0, j = 0; i < big.size(); ++i) {
111+
window[big[i]]++;
112+
if (need[big[i]] >= window[big[i]]) {
113+
--cnt;
114+
}
115+
while (cnt == 0) {
116+
if (i - j + 1 < mi) {
117+
mi = i - j + 1;
118+
k = j;
119+
}
120+
if (need[big[j]] >= window[big[j]]) {
121+
++cnt;
122+
}
123+
window[big[j++]]--;
124+
}
125+
}
126+
if (k < 0) {
127+
return {};
128+
}
129+
return {k, k + mi - 1};
130+
}
131+
};
132+
```
133+
134+
### **Go**
135+
136+
```go
137+
func shortestSeq(big []int, small []int) []int {
138+
cnt := len(small)
139+
need := map[int]int{}
140+
window := map[int]int{}
141+
for _, x := range small {
142+
need[x] = 1
143+
}
144+
j, k, mi := 0, -1, 1<<30
145+
for i, x := range big {
146+
window[x]++
147+
if need[x] >= window[x] {
148+
cnt--
149+
}
150+
for cnt == 0 {
151+
if t := i - j + 1; t < mi {
152+
mi = t
153+
k = j
154+
}
155+
if need[big[j]] >= window[big[j]] {
156+
cnt++
157+
}
158+
window[big[j]]--
159+
j++
160+
}
161+
}
162+
if k < 0 {
163+
return []int{}
164+
}
165+
return []int{k, k + mi - 1}
166+
}
167+
```
50168

169+
### **TypeScript**
170+
171+
```ts
172+
function shortestSeq(big: number[], small: number[]): number[] {
173+
let cnt = small.length;
174+
const need: Map<number, number> = new Map();
175+
const window: Map<number, number> = new Map();
176+
for (const x of small) {
177+
need.set(x, 1);
178+
}
179+
let k = -1;
180+
let mi = 1 << 30;
181+
for (let i = 0, j = 0; i < big.length; ++i) {
182+
window.set(big[i], (window.get(big[i]) ?? 0) + 1);
183+
if ((need.get(big[i]) ?? 0) >= window.get(big[i])!) {
184+
--cnt;
185+
}
186+
while (cnt === 0) {
187+
if (i - j + 1 < mi) {
188+
mi = i - j + 1;
189+
k = j;
190+
}
191+
if ((need.get(big[j]) ?? 0) >= window.get(big[j])!) {
192+
++cnt;
193+
}
194+
window.set(big[j], window.get(big[j])! - 1);
195+
++j;
196+
}
197+
}
198+
return k < 0 ? [] : [k, k + mi - 1];
199+
}
51200
```
52201

53202
### **...**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class Solution {
2+
public:
3+
vector<int> shortestSeq(vector<int>& big, vector<int>& small) {
4+
int cnt = small.size();
5+
unordered_map<int, int> need;
6+
unordered_map<int, int> window;
7+
for (int x : small) {
8+
need[x] = 1;
9+
}
10+
int k = -1, mi = 1 << 30;
11+
for (int i = 0, j = 0; i < big.size(); ++i) {
12+
window[big[i]]++;
13+
if (need[big[i]] >= window[big[i]]) {
14+
--cnt;
15+
}
16+
while (cnt == 0) {
17+
if (i - j + 1 < mi) {
18+
mi = i - j + 1;
19+
k = j;
20+
}
21+
if (need[big[j]] >= window[big[j]]) {
22+
++cnt;
23+
}
24+
window[big[j++]]--;
25+
}
26+
}
27+
if (k < 0) {
28+
return {};
29+
}
30+
return {k, k + mi - 1};
31+
}
32+
};

0 commit comments

Comments
 (0)