Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c37cba6

Browse files
feat: update solutions to lc problem: No.0003 (#3893)
No.0003.Longest Substring Without Repeating Characters
1 parent 7f10b62 commit c37cba6

File tree

14 files changed

+309
-383
lines changed

14 files changed

+309
-383
lines changed

‎solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md‎

Lines changed: 104 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ tags:
2626

2727
<pre>
2828
<strong>输入: </strong>s = "abcabcbb"
29-
<strong>输出: </strong>3
29+
<strong>输出: </strong>3
3030
<strong>解释:</strong> 因为无重复字符的最长子串是 <code>"abc"</code>,所以其长度为 3。
3131
</pre>
3232

@@ -62,26 +62,15 @@ tags:
6262

6363
<!-- solution:start -->
6464

65-
### 方法一:双指针 + 哈希表
66-
67-
定义一个哈希表记录当前窗口内出现的字符,记 $i$ 和 $j$ 分别表示不重复子串的开始位置和结束位置,无重复字符子串的最大长度记为 `ans`
65+
### 方法一:滑动窗口
6866

69-
遍历字符串 `s` 的每个字符 $s[j],ドル我们记为 $c$。若 $s[i..j-1]$ 窗口内存在 $c,ドル则 $i$ 循环向右移动,更新哈希表,直至 $s[i..j-1]$ 窗口不存在 `c`,循环结束。将 `c` 加入哈希表中,此时 $s[i..j]$ 窗口内不含重复元素,更新 `ans` 的最大值
67+
我们可以用两个指针 $l$ 和 $r$ 维护一个滑动窗口,使其始终满足窗口内没有重复字符,初始时 $l$ 和 $r$ 都指向字符串的第一个字符。用一个哈希表或者长度为 128ドル$ 的数组 $\textit{cnt}$ 来记录每个字符出现的次数,其中 $\textit{cnt}[c]$ 表示字符 $c$ 出现的次数
7068

71-
最后返回 `ans` 即可
69+
接下来,我们依次移动右指针 $r,ドル每次移动时,将 $\textit{cnt}[s[r]]$ 的值加 1ドル,ドル然后判断当前窗口 $[l, r]$ 内 $\textit{cnt}[s[r]]$ 是否大于 1ドル,ドル如果大于 1ドル,ドル说明当前窗口内有重复字符,我们需要移动左指针 $l,ドル直到窗口内没有重复字符为止。然后,我们更新答案 $\textit{ans} = \max(\textit{ans}, r - l + 1)$
7270

73-
时间复杂度 $O(n),ドル其中 $n$ 表示字符串 `s` 的长度
71+
最终,我们返回答案 $\textit{ans}$ 即可
7472

75-
双指针算法模板:
76-
77-
```java
78-
for (int i = 0, j = 0; i < n; ++i) {
79-
while (j < i && check(j, i)) {
80-
++j;
81-
}
82-
// 具体问题的逻辑
83-
}
84-
```
73+
时间复杂度 $O(n),ドル其中 $n$ 为字符串的长度。空间复杂度 $O(|\Sigma|),ドル其中 $\Sigma$ 表示字符集,这里 $\Sigma$ 的大小为 128ドル$。
8574

8675
<!-- tabs:start -->
8776

@@ -90,14 +79,14 @@ for (int i = 0, j = 0; i < n; ++i) {
9079
```python
9180
class Solution:
9281
def lengthOfLongestSubstring(self, s: str) -> int:
93-
ss = set()
94-
ans = i = 0
95-
for j, c in enumerate(s):
96-
while c in ss:
97-
ss.remove(s[i])
98-
i += 1
99-
ss.add(c)
100-
ans = max(ans, j - i + 1)
82+
cnt = Counter()
83+
ans = l = 0
84+
for r, c in enumerate(s):
85+
cnt[c] +=1
86+
while cnt[c] >1:
87+
cnt[s[l]] -= 1
88+
l +=1
89+
ans = max(ans, r - l + 1)
10190
return ans
10291
```
10392

@@ -106,15 +95,15 @@ class Solution:
10695
```java
10796
class Solution {
10897
public int lengthOfLongestSubstring(String s) {
109-
boolean[] ss = new boolean[128];
110-
int ans = 0;
111-
for (int i = 0, j = 0; j < s.length(); ++j) {
112-
char c = s.charAt(j);
113-
while (ss[c]) {
114-
ss[s.charAt(i++)] = false;
98+
int[] cnt = new int[128];
99+
int ans = 0, n = s.length();
100+
for (int l = 0, r = 0; r < n; ++r) {
101+
char c = s.charAt(r);
102+
++cnt[c];
103+
while (cnt[c] > 1) {
104+
--cnt[s.charAt(l++)];
115105
}
116-
ss[c] = true;
117-
ans = Math.max(ans, j - i + 1);
106+
ans = Math.max(ans, r - l + 1);
118107
}
119108
return ans;
120109
}
@@ -127,14 +116,14 @@ class Solution {
127116
class Solution {
128117
public:
129118
int lengthOfLongestSubstring(string s) {
130-
bool ss[128]{};
131-
int ans = 0;
132-
for (int i = 0, j = 0; j < s.size(); ++j) {
133-
while (ss[s[j]]) {
134-
ss[s[i++]] = false;
119+
int cnt[128]{};
120+
int ans = 0, n = s.size();
121+
for (int l = 0, r = 0; r < n; ++r) {
122+
++cnt[s[r]];
123+
while (cnt[s[r]] > 1) {
124+
--cnt[s[l++]];
135125
}
136-
ss[s[j]] = true;
137-
ans = max(ans, j - i + 1);
126+
ans = max(ans, r - l + 1);
138127
}
139128
return ans;
140129
}
@@ -145,14 +134,15 @@ public:
145134
146135
```go
147136
func lengthOfLongestSubstring(s string) (ans int) {
148-
ss := [128]bool{}
149-
for i, j := 0, 0; j < len(s); j++ {
150-
for ss[s[j]] {
151-
ss[s[i]] = false
152-
i++
137+
cnt := [128]int{}
138+
l := 0
139+
for r, c := range s {
140+
cnt[c]++
141+
for cnt[c] > 1 {
142+
cnt[s[l]]--
143+
l++
153144
}
154-
ss[s[j]] = true
155-
ans = max(ans, j-i+1)
145+
ans = max(ans, r-l+1)
156146
}
157147
return
158148
}
@@ -163,13 +153,15 @@ func lengthOfLongestSubstring(s string) (ans int) {
163153
```ts
164154
function lengthOfLongestSubstring(s: string): number {
165155
let ans = 0;
166-
const ss: Set<string> = new Set();
167-
for (let i = 0, j = 0; j < s.length; ++j) {
168-
while (ss.has(s[j])) {
169-
ss.delete(s[i++]);
156+
const cnt = new Map<string, number>();
157+
const n = s.length;
158+
for (let l = 0, r = 0; r < n; ++r) {
159+
cnt.set(s[r], (cnt.get(s[r]) || 0) + 1);
160+
while (cnt.get(s[r])! > 1) {
161+
cnt.set(s[l], cnt.get(s[l])! - 1);
162+
++l;
170163
}
171-
ss.add(s[j]);
172-
ans = Math.max(ans, j - i + 1);
164+
ans = Math.max(ans, r - l + 1);
173165
}
174166
return ans;
175167
}
@@ -178,24 +170,22 @@ function lengthOfLongestSubstring(s: string): number {
178170
#### Rust
179171

180172
```rust
181-
use std::collections::HashSet;
182-
183173
impl Solution {
184174
pub fn length_of_longest_substring(s: String) -> i32 {
185-
let s=s.as_bytes();
186-
let mut ss = HashSet::new();
187-
let mut i = 0;
188-
s.iter()
189-
.map(|c| {
190-
whiless.contains(&c) {
191-
ss.remove(&s[i]);
192-
i+=1;
193-
}
194-
ss.insert(c);
195-
ss.len()
196-
})
197-
.max()
198-
.unwrap_or(0) asi32
175+
let mutcnt= [0; 128];
176+
let mut ans = 0;
177+
let mut l = 0;
178+
letchars:Vec<char> =s.chars().collect();
179+
letn=chars.len();
180+
for (r, &c) inchars.iter().enumerate() {
181+
cnt[casusize] +=1;
182+
whilecnt[casusize] >1 {
183+
cnt[chars[l] asusize] -=1;
184+
l+=1;
185+
}
186+
ans=ans.max((r-l+1) asi32);
187+
}
188+
ans
199189
}
200190
}
201191
```
@@ -209,13 +199,15 @@ impl Solution {
209199
*/
210200
var lengthOfLongestSubstring = function (s) {
211201
let ans = 0;
212-
const ss = new Set();
213-
for (let i = 0, j = 0; j < s.length; ++j) {
214-
while (ss.has(s[j])) {
215-
ss.delete(s[i++]);
202+
const n = s.length;
203+
const cnt = new Map();
204+
for (let l = 0, r = 0; r < n; ++r) {
205+
cnt.set(s[r], (cnt.get(s[r]) || 0) + 1);
206+
while (cnt.get(s[r]) > 1) {
207+
cnt.set(s[l], cnt.get(s[l]) - 1);
208+
++l;
216209
}
217-
ss.add(s[j]);
218-
ans = Math.max(ans, j - i + 1);
210+
ans = Math.max(ans, r - l + 1);
219211
}
220212
return ans;
221213
};
@@ -226,14 +218,15 @@ var lengthOfLongestSubstring = function (s) {
226218
```cs
227219
public class Solution {
228220
public int LengthOfLongestSubstring(string s) {
221+
int n = s.Length;
229222
int ans = 0;
230-
var ss = new HashSet<char>();
231-
for (int i = 0, j = 0; j < s.Length; ++j) {
232-
while (ss.Contains(s[j])) {
233-
ss.Remove(s[i++]);
223+
var cnt = new int[128];
224+
for (int l = 0, r = 0; r < n; ++r) {
225+
++cnt[s[r]];
226+
while (cnt[s[r]] > 1) {
227+
--cnt[s[l++]];
234228
}
235-
ss.Add(s[j]);
236-
ans = Math.Max(ans, j - i + 1);
229+
ans = Math.Max(ans, r - l + 1);
237230
}
238231
return ans;
239232
}
@@ -244,19 +237,18 @@ public class Solution {
244237

245238
```php
246239
class Solution {
247-
/**
248-
* @param String $s
249-
* @return Integer
250-
*/
251240
function lengthOfLongestSubstring($s) {
241+
$n = strlen($s);
252242
$ans = 0;
253-
$ss = [];
254-
for ($i = 0, $j = 0; $j < strlen($s); ++$j) {
255-
while (in_array($s[$j], $ss)) {
256-
unset($ss[array_search($s[$i++], $ss)]);
243+
$cnt = array_fill(0, 128, 0);
244+
$l = 0;
245+
for ($r = 0; $r < $n; ++$r) {
246+
$cnt[ord($s[$r])]++;
247+
while ($cnt[ord($s[$r])] > 1) {
248+
$cnt[ord($s[$l])]--;
249+
$l++;
257250
}
258-
$ss[] = $s[$j];
259-
$ans = max($ans, $j - $i + 1);
251+
$ans = max($ans, $r - $l + 1);
260252
}
261253
return $ans;
262254
}
@@ -268,62 +260,40 @@ class Solution {
268260
```swift
269261
class Solution {
270262
func lengthOfLongestSubstring(_ s: String) -> Int {
271-
var map = [Character:Int]()
272-
var currentStartingIndex = 0
273-
var i = 0
274-
var maxLength = 0
275-
for char in s {
276-
if map[char] !=nil {
277-
if map[char]!>= currentStartingIndex {
278-
maxLength =max(maxLength, i - currentStartingIndex)
279-
currentStartingIndex = map[char]!+ 1
280-
}
263+
let n = s.count
264+
var ans = 0
265+
var cnt = [Int](repeating: 0, count: 128)
266+
var l = 0
267+
let sArray =Array(s)
268+
for r in0..<n {
269+
cnt[Int(sArray[r].asciiValue!)] +=1
270+
while cnt[Int(sArray[r].asciiValue!)] >1 {
271+
cnt[Int(sArray[l].asciiValue!)] -= 1
272+
l +=1
281273
}
282-
map[char] = i
283-
i += 1
274+
ans = max(ans, r - l + 1)
284275
}
285-
return max(maxLength, i - currentStartingIndex)
276+
return ans
286277
}
287278
}
288279
```
289280

290-
#### Nim
291-
292-
```nim
293-
proc lengthOfLongestSubstring(s: string): int =
294-
var
295-
i = 0
296-
j = 0
297-
res = 0
298-
literals: set[char] = {}
299-
300-
while i < s.len:
301-
while s[i] in literals:
302-
if s[j] in literals:
303-
excl(literals, s[j])
304-
j += 1
305-
literals.incl(s[i]) # Uniform Function Call Syntax f(x) = x.f
306-
res = max(res, i - j + 1)
307-
i += 1
308-
309-
result = res # result has the default return value
310-
```
311-
312281
#### Kotlin
313282

314283
```kotlin
315284
class Solution {
316285
fun lengthOfLongestSubstring(s: String): Int {
317-
var char_set = BooleanArray(128)
318-
var left = 0
286+
val n = s.length
319287
var ans = 0
320-
s.forEachIndexed { right, c ->
321-
while (char_set[c.code]) {
322-
char_set[s[left].code] = false
323-
left++
288+
val cnt = IntArray(128)
289+
var l = 0
290+
for (r in 0 until n) {
291+
cnt[s[r].toInt()]++
292+
while (cnt[s[r].toInt()] > 1) {
293+
cnt[s[l].toInt()]--
294+
l++
324295
}
325-
char_set[c.code] = true
326-
ans = Math.max(ans, right - left + 1)
296+
ans = Math.max(ans, r - l + 1)
327297
}
328298
return ans
329299
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /