Skip to content

Commit 8b35f78

Browse files
committed
feat: add solutions to lcci problem: No.17.05
No.17.05.Find Longest Subarray
1 parent 7d763e8 commit 8b35f78

File tree

6 files changed

+142
-140
lines changed

6 files changed

+142
-140
lines changed

lcci/17.05.Find Longest Subarray/README.md

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,20 @@
3333

3434
<!-- 这里可写通用的实现逻辑 -->
3535

36-
前缀和 + 哈希表
36+
**方法一:前缀和 + 哈希表**
3737

38-
遍历字符串数组 array,将数字视为 1,字母视为 -1(或者反过来),题目转换为元素和为 0 的最长子数组。
38+
题目要求找到最长的子数组,且包含的字符和数字的个数相同。我们可以将字符看作 $1$,数字看作 $-1$,那么问题就转化为:求最长的子数组,使得该子数组的和为 $0$。
39+
40+
我们可以运用前缀和的思想,用哈希表 $vis$ 记录每个前缀和第一次出现的位置,用变量 $mx$ 和 $k$ 分别记录最长的满足条件的子数组的长度和左端点位置。
41+
42+
遍历数组,计算当前位置 $i$ 的前缀和 $s$:
43+
44+
- 如果当前位置的前缀和 $s$ 在哈希表 $vis$ 中存在,我们记第一次出现 $s$ 的位置为 $j$,那么区间 $[j + 1,..,i]$ 的子数组和就为 $0$。如果此前的最长子数组的长度小于当前子数组的长度,即 $mx \lt i - j$,我们就更新 $mx = i - j$ 和 $k = j + 1$。
45+
- 否则,我们将当前位置的前缀和 $s$ 作为键,当前位置 $i$ 作为值,存入哈希表 $vis$ 中。
46+
47+
遍历结束后,如果 $mx = 0$,说明不存在这样的子数组,返回空数组;否则,返回区间 $[k,..,k + mx - 1]$ 的子数组即可。
48+
49+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。
3950

4051
<!-- tabs:start -->
4152

@@ -46,18 +57,17 @@
4657
```python
4758
class Solution:
4859
def findLongestSubarray(self, array: List[str]) -> List[str]:
49-
seen = {0: -1}
50-
t = mx = 0
51-
ans = []
52-
for i, s in enumerate(array):
53-
t += 1 if s.isalpha() else -1
54-
if t in seen:
55-
if mx < i - seen[t]:
56-
mx = i - seen[t]
57-
ans = array[seen[t] + 1 : i + 1]
60+
vis = {0: -1}
61+
s = mx = k = 0
62+
for i, x in enumerate(array):
63+
s += 1 if x.isalpha() else -1
64+
if s in vis:
65+
if mx < i - (j := vis[s]):
66+
mx = i - j
67+
k = j + 1
5868
else:
59-
seen[t] = i
60-
return ans
69+
vis[s] = i
70+
return [] if mx == 0 else array[k: k + mx]
6171
```
6272

6373
### **Java**
@@ -67,25 +77,23 @@ class Solution:
6777
```java
6878
class Solution {
6979
public String[] findLongestSubarray(String[] array) {
70-
Map<Integer, Integer> seen = new HashMap<>();
71-
seen.put(0, -1);
72-
int t = 0, mx = 0;
73-
int j = 0;
80+
Map<Integer, Integer> vis = new HashMap<>();
81+
vis.put(0, -1);
82+
int s = 0, mx = 0, k = 0;
7483
for (int i = 0; i < array.length; ++i) {
75-
t += Character.isDigit(array[i].charAt(0)) ? 1 : -1;
76-
if (seen.containsKey(t)) {
77-
if (mx < i - seen.get(t)) {
78-
mx = i - seen.get(t);
79-
j = seen.get(t) + 1;
84+
s += array[i].charAt(0) >= 'A' ? 1 : -1;
85+
if (vis.containsKey(s)) {
86+
int j = vis.get(s);
87+
if (mx < i - j) {
88+
mx = i - j;
89+
k = j + 1;
8090
}
8191
} else {
82-
seen.put(t, i);
92+
vis.put(s, i);
8393
}
8494
}
8595
String[] ans = new String[mx];
86-
for (int i = 0; i < mx; ++i) {
87-
ans[i] = array[i + j];
88-
}
96+
System.arraycopy(array, k, ans, 0, mx);
8997
return ans;
9098
}
9199
}
@@ -97,21 +105,21 @@ class Solution {
97105
class Solution {
98106
public:
99107
vector<string> findLongestSubarray(vector<string>& array) {
100-
unordered_map<int, int> seen;
101-
seen[0] = -1;
102-
int t = 0, mx = 0, j = 0;
108+
unordered_map<int, int> vis{{0, -1}};
109+
int s = 0, mx = 0, k = 0;
103110
for (int i = 0; i < array.size(); ++i) {
104-
t += isdigit(array[i][0]) ? 1 : -1;
105-
if (seen.count(t)) {
106-
if (mx < i - seen[t]) {
107-
mx = i - seen[t];
108-
j = seen[t] + 1;
111+
s += array[i][0] >= 'A' ? 1 : -1;
112+
if (vis.count(s)) {
113+
int j = vis[s];
114+
if (mx < i - j) {
115+
mx = i - j;
116+
k = j + 1;
109117
}
110118
} else {
111-
seen[t] = i;
119+
vis[s] = i;
112120
}
113121
}
114-
return {array.begin() + j, array.begin() + j + mx};
122+
return vector<string>(array.begin() + k, array.begin() + k + mx);
115123
}
116124
};
117125
```
@@ -120,24 +128,24 @@ public:
120128
121129
```go
122130
func findLongestSubarray(array []string) []string {
123-
seen := map[int]int{0: -1}
124-
t, mx, j := 0, 0, 0
125-
for i, s := range array {
126-
if unicode.IsDigit(rune(s[0])) {
127-
t++
131+
vis := map[int]int{0: -1}
132+
var s, mx, k int
133+
for i, x := range array {
134+
if x[0] >= 'A' {
135+
s++
128136
} else {
129-
t--
137+
s--
130138
}
131-
if k, ok := seen[t]; ok {
132-
if mx < i-k {
133-
mx = i - k
134-
j = k + 1
139+
if j, ok := vis[s]; ok {
140+
if mx < i-j {
141+
mx = i - j
142+
k = j + 1
135143
}
136144
} else {
137-
seen[t] = i
145+
vis[s] = i
138146
}
139147
}
140-
return array[j : j+mx]
148+
return array[k : k+mx]
141149
}
142150
```
143151

lcci/17.05.Find Longest Subarray/README_EN.md

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -47,44 +47,41 @@
4747
```python
4848
class Solution:
4949
def findLongestSubarray(self, array: List[str]) -> List[str]:
50-
seen = {0: -1}
51-
t = mx = 0
52-
ans = []
53-
for i, s in enumerate(array):
54-
t += 1 if s.isalpha() else -1
55-
if t in seen:
56-
if mx < i - seen[t]:
57-
mx = i - seen[t]
58-
ans = array[seen[t] + 1 : i + 1]
50+
vis = {0: -1}
51+
s = mx = k = 0
52+
for i, x in enumerate(array):
53+
s += 1 if x.isalpha() else -1
54+
if s in vis:
55+
if mx < i - (j := vis[s]):
56+
mx = i - j
57+
k = j + 1
5958
else:
60-
seen[t] = i
61-
return ans
59+
vis[s] = i
60+
return [] if mx == 0 else array[k: k + mx]
6261
```
6362

6463
### **Java**
6564

6665
```java
6766
class Solution {
6867
public String[] findLongestSubarray(String[] array) {
69-
Map<Integer, Integer> seen = new HashMap<>();
70-
seen.put(0, -1);
71-
int t = 0, mx = 0;
72-
int j = 0;
68+
Map<Integer, Integer> vis = new HashMap<>();
69+
vis.put(0, -1);
70+
int s = 0, mx = 0, k = 0;
7371
for (int i = 0; i < array.length; ++i) {
74-
t += Character.isDigit(array[i].charAt(0)) ? 1 : -1;
75-
if (seen.containsKey(t)) {
76-
if (mx < i - seen.get(t)) {
77-
mx = i - seen.get(t);
78-
j = seen.get(t) + 1;
72+
s += array[i].charAt(0) >= 'A' ? 1 : -1;
73+
if (vis.containsKey(s)) {
74+
int j = vis.get(s);
75+
if (mx < i - j) {
76+
mx = i - j;
77+
k = j + 1;
7978
}
8079
} else {
81-
seen.put(t, i);
80+
vis.put(s, i);
8281
}
8382
}
8483
String[] ans = new String[mx];
85-
for (int i = 0; i < mx; ++i) {
86-
ans[i] = array[i + j];
87-
}
84+
System.arraycopy(array, k, ans, 0, mx);
8885
return ans;
8986
}
9087
}
@@ -96,21 +93,21 @@ class Solution {
9693
class Solution {
9794
public:
9895
vector<string> findLongestSubarray(vector<string>& array) {
99-
unordered_map<int, int> seen;
100-
seen[0] = -1;
101-
int t = 0, mx = 0, j = 0;
96+
unordered_map<int, int> vis{{0, -1}};
97+
int s = 0, mx = 0, k = 0;
10298
for (int i = 0; i < array.size(); ++i) {
103-
t += isdigit(array[i][0]) ? 1 : -1;
104-
if (seen.count(t)) {
105-
if (mx < i - seen[t]) {
106-
mx = i - seen[t];
107-
j = seen[t] + 1;
99+
s += array[i][0] >= 'A' ? 1 : -1;
100+
if (vis.count(s)) {
101+
int j = vis[s];
102+
if (mx < i - j) {
103+
mx = i - j;
104+
k = j + 1;
108105
}
109106
} else {
110-
seen[t] = i;
107+
vis[s] = i;
111108
}
112109
}
113-
return {array.begin() + j, array.begin() + j + mx};
110+
return vector<string>(array.begin() + k, array.begin() + k + mx);
114111
}
115112
};
116113
```
@@ -119,24 +116,24 @@ public:
119116
120117
```go
121118
func findLongestSubarray(array []string) []string {
122-
seen := map[int]int{0: -1}
123-
t, mx, j := 0, 0, 0
124-
for i, s := range array {
125-
if unicode.IsDigit(rune(s[0])) {
126-
t++
119+
vis := map[int]int{0: -1}
120+
var s, mx, k int
121+
for i, x := range array {
122+
if x[0] >= 'A' {
123+
s++
127124
} else {
128-
t--
125+
s--
129126
}
130-
if k, ok := seen[t]; ok {
131-
if mx < i-k {
132-
mx = i - k
133-
j = k + 1
127+
if j, ok := vis[s]; ok {
128+
if mx < i-j {
129+
mx = i - j
130+
k = j + 1
134131
}
135132
} else {
136-
seen[t] = i
133+
vis[s] = i
137134
}
138135
}
139-
return array[j : j+mx]
136+
return array[k : k+mx]
140137
}
141138
```
142139

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
class Solution {
22
public:
33
vector<string> findLongestSubarray(vector<string>& array) {
4-
unordered_map<int, int> seen;
5-
seen[0] = -1;
6-
int t = 0, mx = 0, j = 0;
4+
unordered_map<int, int> vis{{0, -1}};
5+
int s = 0, mx = 0, k = 0;
76
for (int i = 0; i < array.size(); ++i) {
8-
t += isdigit(array[i][0]) ? 1 : -1;
9-
if (seen.count(t)) {
10-
if (mx < i - seen[t]) {
11-
mx = i - seen[t];
12-
j = seen[t] + 1;
7+
s += array[i][0] >= 'A' ? 1 : -1;
8+
if (vis.count(s)) {
9+
int j = vis[s];
10+
if (mx < i - j) {
11+
mx = i - j;
12+
k = j + 1;
1313
}
1414
} else {
15-
seen[t] = i;
15+
vis[s] = i;
1616
}
1717
}
18-
return {array.begin() + j, array.begin() + j + mx};
18+
return vector<string>(array.begin() + k, array.begin() + k + mx);
1919
}
2020
};
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
func findLongestSubarray(array []string) []string {
2-
seen := map[int]int{0: -1}
3-
t, mx, j := 0, 0, 0
4-
for i, s := range array {
5-
if unicode.IsDigit(rune(s[0])) {
6-
t++
2+
vis := map[int]int{0: -1}
3+
var s, mx, k int
4+
for i, x := range array {
5+
if x[0] >= 'A' {
6+
s++
77
} else {
8-
t--
8+
s--
99
}
10-
if k, ok := seen[t]; ok {
11-
if mx < i-k {
12-
mx = i - k
13-
j = k + 1
10+
if j, ok := vis[s]; ok {
11+
if mx < i-j {
12+
mx = i - j
13+
k = j + 1
1414
}
1515
} else {
16-
seen[t] = i
16+
vis[s] = i
1717
}
1818
}
19-
return array[j : j+mx]
19+
return array[k : k+mx]
2020
}
Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
class Solution {
22
public String[] findLongestSubarray(String[] array) {
3-
Map<Integer, Integer> seen = new HashMap<>();
4-
seen.put(0, -1);
5-
int t = 0, mx = 0;
6-
int j = 0;
3+
Map<Integer, Integer> vis = new HashMap<>();
4+
vis.put(0, -1);
5+
int s = 0, mx = 0, k = 0;
76
for (int i = 0; i < array.length; ++i) {
8-
t += Character.isDigit(array[i].charAt(0)) ? 1 : -1;
9-
if (seen.containsKey(t)) {
10-
if (mx < i - seen.get(t)) {
11-
mx = i - seen.get(t);
12-
j = seen.get(t) + 1;
7+
s += array[i].charAt(0) >= 'A' ? 1 : -1;
8+
if (vis.containsKey(s)) {
9+
int j = vis.get(s);
10+
if (mx < i - j) {
11+
mx = i - j;
12+
k = j + 1;
1313
}
1414
} else {
15-
seen.put(t, i);
15+
vis.put(s, i);
1616
}
1717
}
1818
String[] ans = new String[mx];
19-
for (int i = 0; i < mx; ++i) {
20-
ans[i] = array[i + j];
21-
}
19+
System.arraycopy(array, k, ans, 0, mx);
2220
return ans;
2321
}
2422
}

0 commit comments

Comments
 (0)