Skip to content

Commit

Permalink
feat: add solutions to lcof problem: No.48
Browse files Browse the repository at this point in the history
  • Loading branch information
yanglbme committed Feb 3, 2023
1 parent 656d42b commit db780ce
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 141 deletions.
154 changes: 73 additions & 81 deletions lcof/面试题48. 最长不含重复字符的子字符串/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@

## 解法

“滑动窗口 + 哈希表”。
**方法一:双指针 + 哈希表**

定义一个哈希表记录当前窗口内出现的字符,i、j 分别表示不重复子串的结束位置和开始位置,res 表示无重复字符子串的最大长度
我们用双指针 $j$ 和 $i$ 分别表示子串的左右边界,其中 $j$ 是滑动窗口的左边界,$i$ 是滑动窗口的右边界,用哈希表 $vis$ 记录每个字符是否出现过

遍历 i,若 `[j, i - 1]` 窗口内存在 `s[i]`,则 j 循环向右移动,更新哈希表,直至 `[j, i - 1]` 窗口不存在 `s[i]`,循环结束。将 `s[i]` 加入哈希表中,此时 `[j, i]` 窗口内不含重复元素,更新 res 的最大值:`res = max(res, i - j + 1)`
遍历字符串 $s$,如果此时 $s[i]$ 在哈希表 $vis$ 中存在,说明 $s[i]$ 重复了,我们需要将左边界 $j$ 右移,直到 $s[i]$ 不在哈希表 $vis$ 中为止,然后将 $s[i]$ 加入哈希表 $vis$ 中。此时,我们更新无重复字符子串的最大长度,即 $ans = max(ans, i - j + 1)$

最后返回 res 即可。
遍历结束后,我们返回 $ans$ 即可。

时间复杂度 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 是字符串 $s$ 的长度;而 $C$ 是字符集的大小。

<!-- tabs:start -->

Expand All @@ -55,35 +57,46 @@
```python
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
i = j = res = 0
chars = set()
while i < len(s):
while s[i] in chars:
if s[j] in chars:
chars.remove(s[j])
cnt = Counter()
ans = j = 0
for i, c in enumerate(s):
cnt[c] += 1
while cnt[c] > 1:
cnt[s[j]] -= 1
j += 1
chars.add(s[i])
res = max(res, i - j + 1)
i += 1
return res
ans = max(ans, i - j + 1)
return ans
```

```python
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
vis = set()
ans = j = 0
for i, c in enumerate(s):
while c in vis:
vis.remove(s[j])
j += 1
vis.add(c)
ans = max(ans, i - j + 1)
return ans
```

### **Java**

```java
class Solution {
public int lengthOfLongestSubstring(String s) {
int res = 0;
Set<Character> set = new HashSet<>();
for (int i = 0, j = 0; i < s.length(); ++i) {
char c = s.charAt(i);
while (set.contains(c)) {
set.remove(s.charAt(j++));
int ans = 0, j = 0;
Set<Character> vis = new HashSet<>();
for (int i = 0; i < s.length(); ++i) {
while (vis.contains(s.charAt(i))) {
vis.remove(s.charAt(j++));
}
set.add(c);
res = Math.max(res, i - j + 1);
vis.add(s.charAt(i));
ans = Math.max(ans, i - j + 1);
}
return res;
return ans;
}
}
```
Expand All @@ -94,35 +107,35 @@ class Solution {
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int res = 0;
unordered_set<char> chars;
int ans = 0;
unordered_set<char> vis;
for (int i = 0, j = 0; i < s.size(); ++i) {
while (chars.count(s[i])) {
chars.erase(s[j++]);
while (vis.count(s[i])) {
vis.erase(s[j++]);
}
chars.insert(s[i]);
res = max(res, i - j + 1);
vis.insert(s[i]);
ans = max(ans, i - j + 1);
}
return res;
return ans;
}
};
```
### **Go**
```go
func lengthOfLongestSubstring(s string) int {
chars := make(map[byte]bool)
res := 0
for i, j := 0, 0; i < len(s); i++ {
for chars[s[i]] {
chars[s[j]] = false
func lengthOfLongestSubstring(s string) (ans int) {
vis := map[byte]bool{}
j := 0
for i := range s {
for vis[s[i]] {
vis[s[j]] = false
j++
}
chars[s[i]] = true
res = max(res, i-j+1)
vis[s[i]] = true
ans = max(ans, i-j+1)
}
return res
return
}
func max(a, b int) int {
Expand All @@ -141,53 +154,33 @@ func max(a, b int) int {
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
let res = 0;
let chars = new Set();
let ans = 0;
let vis = new Set();
for (let i = 0, j = 0; i < s.length; ++i) {
while (chars.has(s[i])) {
chars.delete(s[j++]);
while (vis.has(s[i])) {
vis.delete(s[j++]);
}
chars.add(s[i]);
res = Math.max(res, i - j + 1);
vis.add(s[i]);
ans = Math.max(ans, i - j + 1);
}
return res;
return ans;
};
```

### **TypeScript**

```ts
function lengthOfLongestSubstring(s: string): number {
const n = s.length;
const set = new Set<string>();
let res = 0;
let i = 0;
for (let j = 0; j < n; j++) {
const c = s[j];
while (set.has(c)) {
set.delete(s[i++]);
}
set.add(c);
res = Math.max(res, set.size);
}
return res;
}
```

```ts
function lengthOfLongestSubstring(s: string): number {
const map = new Map<string, number>();
const n = s.length;
let res = 0;
let i = -1;
for (let j = 0; j < n; j++) {
if (map.has(s[j])) {
i = Math.max(i, map.get(s[j]));
let ans = 0;
let vis = new Set<string>();
for (let i = 0, j = 0; i < s.length; ++i) {
while (vis.has(s[i])) {
vis.delete(s[j++]);
}
map.set(s[j], j);
res = Math.max(res, j - i);
vis.add(s[i]);
ans = Math.max(ans, i - j + 1);
}
return res;
return ans;
}
```

Expand Down Expand Up @@ -243,15 +236,14 @@ impl Solution {
```cs
public class Solution {
public int LengthOfLongestSubstring(string s) {
var set = new HashSet<char>();
var vis = new HashSet<char>();
int ans = 0;
for (int l=0, r=0; r < s.Length; r++) {
while (set.Contains(s[r]))
{
set.Remove(s[l++]);
for (int i = 0, j = 0; i < s.Length; ++i) {
while (vis.Contains(s[i])) {
vis.Remove(s[j++]);
}
ans = Math.Max(r - l + 1, ans);
set.Add(s[r]);
vis.Add(s[i]);
ans = Math.Max(ans, i - j + 1);
}
return ans;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int res = 0;
unordered_set<char> chars;
int ans = 0;
unordered_set<char> vis;
for (int i = 0, j = 0; i < s.size(); ++i) {
while (chars.count(s[i])) {
chars.erase(s[j++]);
while (vis.count(s[i])) {
vis.erase(s[j++]);
}
chars.insert(s[i]);
res = max(res, i - j + 1);
vis.insert(s[i]);
ans = max(ans, i - j + 1);
}
return res;
return ans;
}
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
public class Solution {
public int LengthOfLongestSubstring(string s) {
var set = new HashSet<char>();
var vis = new HashSet<char>();
int ans = 0;
for (int l=0, r=0; r < s.Length; r++) {
while (set.Contains(s[r]))
{
set.Remove(s[l++]);
for (int i = 0, j = 0; i < s.Length; ++i) {
while (vis.Contains(s[i])) {
vis.Remove(s[j++]);
}
ans = Math.Max(r - l + 1, ans);
set.Add(s[r]);
vis.Add(s[i]);
ans = Math.Max(ans, i - j + 1);
}
return ans;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
func lengthOfLongestSubstring(s string) int {
chars := make(map[byte]bool)
res := 0
for i, j := 0, 0; i < len(s); i++ {
for chars[s[i]] {
chars[s[j]] = false
func lengthOfLongestSubstring(s string) (ans int) {
vis := map[byte]bool{}
j := 0
for i := range s {
for vis[s[i]] {
vis[s[j]] = false
j++
}
chars[s[i]] = true
res = max(res, i-j+1)
vis[s[i]] = true
ans = max(ans, i-j+1)
}
return res
return
}

func max(a, b int) int {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
class Solution {
public int lengthOfLongestSubstring(String s) {
int res = 0;
Set<Character> set = new HashSet<>();
for (int i = 0, j = 0; i < s.length(); ++i) {
char c = s.charAt(i);
while (set.contains(c)) {
set.remove(s.charAt(j++));
int ans = 0, j = 0;
Set<Character> vis = new HashSet<>();
for (int i = 0; i < s.length(); ++i) {
while (vis.contains(s.charAt(i))) {
vis.remove(s.charAt(j++));
}
set.add(c);
res = Math.max(res, i - j + 1);
vis.add(s.charAt(i));
ans = Math.max(ans, i - j + 1);
}
return res;
return ans;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
let res = 0;
let chars = new Set();
let ans = 0;
let vis = new Set();
for (let i = 0, j = 0; i < s.length; ++i) {
while (chars.has(s[i])) {
chars.delete(s[j++]);
while (vis.has(s[i])) {
vis.delete(s[j++]);
}
chars.add(s[i]);
res = Math.max(res, i - j + 1);
vis.add(s[i]);
ans = Math.max(ans, i - j + 1);
}
return res;
return ans;
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
i = j = res = 0
chars = set()
while i < len(s):
while s[i] in chars:
if s[j] in chars:
chars.remove(s[j])
vis = set()
ans = j = 0
for i, c in enumerate(s):
while c in vis:
vis.remove(s[j])
j += 1
chars.add(s[i])
res = max(res, i - j + 1)
i += 1
return res
vis.add(c)
ans = max(ans, i - j + 1)
return ans
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
function lengthOfLongestSubstring(s: string): number {
const n = s.length;
const set = new Set<string>();
let res = 0;
let i = 0;
for (let j = 0; j < n; j++) {
const c = s[j];
while (set.has(c)) {
set.delete(s[i++]);
let ans = 0;
let vis = new Set<string>();
for (let i = 0, j = 0; i < s.length; ++i) {
while (vis.has(s[i])) {
vis.delete(s[j++]);
}
set.add(c);
res = Math.max(res, set.size);
vis.add(s[i]);
ans = Math.max(ans, i - j + 1);
}
return res;
return ans;
}

0 comments on commit db780ce

Please sign in to comment.