Skip to content

feat: update solutions to lc problems: No.0340~0342 #3288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ tags:

### 方法一:滑动窗口 + 哈希表

我们可以使用滑动窗口的思想,维护一个滑动窗口,使得窗口内的字符串中不同字符的个数不超过 $k$ 个。窗口内不同字符个数的统计可以用哈希表 `cnt` 来维护
我们可以使用滑动窗口的思想,用一个哈希表 $\textit{cnt}$ 记录窗口中每个字符的出现次数,用 $\textit{l}$ 记录窗口的左边界

我们使用两个指针 $j$ 和 $i$ 分别表示滑动窗口的左右边界。我们先移动右边界 $i$,将字符 $s[i]$ 加入到窗口内,扩大滑动窗口,若此时窗口内不同字符的个数超过 $k$ 个,则移动左边界 $j$,缩小滑动窗口,直到窗口内不同字符的个数不超过 $k$ 个。此时我们可以更新答案的最大值,即 $ans = max(ans, i - j + 1)$。
遍历字符串,每次将右边界的字符加入哈希表,如果哈希表中不同字符的个数超过了 $k$,则将左边界的字符从哈希表中删除,然后更新左边界 $\textit{l}$。

时间复杂度 $O(n)$,空间复杂度 $O(\min(n, k))$。其中 $n$ 为字符串的长度。
最后返回字符串的长度减去左边界的长度即可。

时间复杂度 $O(n)$,空间复杂度 $O(k)$。其中 $n$ 为字符串的长度。

<!-- tabs:start -->

Expand All @@ -67,18 +69,16 @@ tags:
```python
class Solution:
def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int:
l = 0
cnt = Counter()
n = len(s)
ans = j = 0
for i, c in enumerate(s):
for c in s:
cnt[c] += 1
while len(cnt) > k:
cnt[s[j]] -= 1
if cnt[s[j]] == 0:
cnt.pop(s[j])
j += 1
ans = max(ans, i - j + 1)
return ans
if len(cnt) > k:
cnt[s[l]] -= 1
if cnt[s[l]] == 0:
del cnt[s[l]]
l += 1
return len(s) - l
```

#### Java
Expand All @@ -87,22 +87,18 @@ class Solution:
class Solution {
public int lengthOfLongestSubstringKDistinct(String s, int k) {
Map<Character, Integer> cnt = new HashMap<>();
int n = s.length();
int ans = 0, j = 0;
for (int i = 0; i < n; ++i) {
char c = s.charAt(i);
cnt.put(c, cnt.getOrDefault(c, 0) + 1);
while (cnt.size() > k) {
char t = s.charAt(j);
cnt.put(t, cnt.getOrDefault(t, 0) - 1);
if (cnt.get(t) == 0) {
cnt.remove(t);
int l = 0;
char[] cs = s.toCharArray();
for (char c : cs) {
cnt.merge(c, 1, Integer::sum);
if (cnt.size() > k) {
if (cnt.merge(cs[l], -1, Integer::sum) == 0) {
cnt.remove(cs[l]);
}
++j;
++l;
}
ans = Math.max(ans, i - j + 1);
}
return ans;
return cs.length - l;
}
}
```
Expand All @@ -114,41 +110,58 @@ class Solution {
public:
int lengthOfLongestSubstringKDistinct(string s, int k) {
unordered_map<char, int> cnt;
int n = s.size();
int ans = 0, j = 0;
for (int i = 0; i < n; ++i) {
cnt[s[i]]++;
while (cnt.size() > k) {
if (--cnt[s[j]] == 0) {
cnt.erase(s[j]);
int l = 0;
for (char& c : s) {
++cnt[c];
if (cnt.size() > k) {
if (--cnt[s[l]] == 0) {
cnt.erase(s[l]);
}
++j;
++l;
}
ans = max(ans, i - j + 1);
}
return ans;
return s.size() - l;
}
};
```

#### Go

```go
func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) {
func lengthOfLongestSubstringKDistinct(s string, k int) int {
cnt := map[byte]int{}
j := 0
for i := range s {
cnt[s[i]]++
for len(cnt) > k {
cnt[s[j]]--
if cnt[s[j]] == 0 {
delete(cnt, s[j])
l := 0
for _, c := range s {
cnt[byte(c)]++
if len(cnt) > k {
cnt[s[l]]--
if cnt[s[l]] == 0 {
delete(cnt, s[l])
}
j++
l++
}
ans = max(ans, i-j+1)
}
return
return len(s) - l
}
```

#### TypeScript

```ts
function lengthOfLongestSubstringKDistinct(s: string, k: number): number {
const cnt: Map<string, number> = new Map();
let l = 0;
for (const c of s) {
cnt.set(c, (cnt.get(c) ?? 0) + 1);
if (cnt.size > k) {
cnt.set(s[l], cnt.get(s[l])! - 1);
if (cnt.get(s[l]) === 0) {
cnt.delete(s[l]);
}
l++;
}
}
return s.length - l;
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,15 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: Sliding Window + Hash Table

We can use the idea of a sliding window, with a hash table $\textit{cnt}$ to record the occurrence count of each character within the window, and $\textit{l}$ to denote the left boundary of the window.

Iterate through the string, adding the character at the right boundary to the hash table each time. If the number of distinct characters in the hash table exceeds $k$, remove the character at the left boundary from the hash table, then update the left boundary $\textit{l}$.

Finally, return the length of the string minus the length of the left boundary.

The time complexity is $O(n)$, and the space complexity is $O(k)$. Here, $n$ is the length of the string.

<!-- tabs:start -->

Expand All @@ -59,18 +67,16 @@ tags:
```python
class Solution:
def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int:
l = 0
cnt = Counter()
n = len(s)
ans = j = 0
for i, c in enumerate(s):
for c in s:
cnt[c] += 1
while len(cnt) > k:
cnt[s[j]] -= 1
if cnt[s[j]] == 0:
cnt.pop(s[j])
j += 1
ans = max(ans, i - j + 1)
return ans
if len(cnt) > k:
cnt[s[l]] -= 1
if cnt[s[l]] == 0:
del cnt[s[l]]
l += 1
return len(s) - l
```

#### Java
Expand All @@ -79,22 +85,18 @@ class Solution:
class Solution {
public int lengthOfLongestSubstringKDistinct(String s, int k) {
Map<Character, Integer> cnt = new HashMap<>();
int n = s.length();
int ans = 0, j = 0;
for (int i = 0; i < n; ++i) {
char c = s.charAt(i);
cnt.put(c, cnt.getOrDefault(c, 0) + 1);
while (cnt.size() > k) {
char t = s.charAt(j);
cnt.put(t, cnt.getOrDefault(t, 0) - 1);
if (cnt.get(t) == 0) {
cnt.remove(t);
int l = 0;
char[] cs = s.toCharArray();
for (char c : cs) {
cnt.merge(c, 1, Integer::sum);
if (cnt.size() > k) {
if (cnt.merge(cs[l], -1, Integer::sum) == 0) {
cnt.remove(cs[l]);
}
++j;
++l;
}
ans = Math.max(ans, i - j + 1);
}
return ans;
return cs.length - l;
}
}
```
Expand All @@ -106,41 +108,58 @@ class Solution {
public:
int lengthOfLongestSubstringKDistinct(string s, int k) {
unordered_map<char, int> cnt;
int n = s.size();
int ans = 0, j = 0;
for (int i = 0; i < n; ++i) {
cnt[s[i]]++;
while (cnt.size() > k) {
if (--cnt[s[j]] == 0) {
cnt.erase(s[j]);
int l = 0;
for (char& c : s) {
++cnt[c];
if (cnt.size() > k) {
if (--cnt[s[l]] == 0) {
cnt.erase(s[l]);
}
++j;
++l;
}
ans = max(ans, i - j + 1);
}
return ans;
return s.size() - l;
}
};
```

#### Go

```go
func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) {
func lengthOfLongestSubstringKDistinct(s string, k int) int {
cnt := map[byte]int{}
j := 0
for i := range s {
cnt[s[i]]++
for len(cnt) > k {
cnt[s[j]]--
if cnt[s[j]] == 0 {
delete(cnt, s[j])
l := 0
for _, c := range s {
cnt[byte(c)]++
if len(cnt) > k {
cnt[s[l]]--
if cnt[s[l]] == 0 {
delete(cnt, s[l])
}
j++
l++
}
ans = max(ans, i-j+1)
}
return
return len(s) - l
}
```

#### TypeScript

```ts
function lengthOfLongestSubstringKDistinct(s: string, k: number): number {
const cnt: Map<string, number> = new Map();
let l = 0;
for (const c of s) {
cnt.set(c, (cnt.get(c) ?? 0) + 1);
if (cnt.size > k) {
cnt.set(s[l], cnt.get(s[l])! - 1);
if (cnt.get(s[l]) === 0) {
cnt.delete(s[l]);
}
l++;
}
}
return s.length - l;
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@ class Solution {
public:
int lengthOfLongestSubstringKDistinct(string s, int k) {
unordered_map<char, int> cnt;
int n = s.size();
int ans = 0, j = 0;
for (int i = 0; i < n; ++i) {
cnt[s[i]]++;
while (cnt.size() > k) {
if (--cnt[s[j]] == 0) {
cnt.erase(s[j]);
int l = 0;
for (char& c : s) {
++cnt[c];
if (cnt.size() > k) {
if (--cnt[s[l]] == 0) {
cnt.erase(s[l]);
}
++j;
++l;
}
ans = max(ans, i - j + 1);
}
return ans;
return s.size() - l;
}
};
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) {
func lengthOfLongestSubstringKDistinct(s string, k int) int {
cnt := map[byte]int{}
j := 0
for i := range s {
cnt[s[i]]++
for len(cnt) > k {
cnt[s[j]]--
if cnt[s[j]] == 0 {
delete(cnt, s[j])
l := 0
for _, c := range s {
cnt[byte(c)]++
if len(cnt) > k {
cnt[s[l]]--
if cnt[s[l]] == 0 {
delete(cnt, s[l])
}
j++
l++
}
ans = max(ans, i-j+1)
}
return
return len(s) - l
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
class Solution {
public int lengthOfLongestSubstringKDistinct(String s, int k) {
Map<Character, Integer> cnt = new HashMap<>();
int n = s.length();
int ans = 0, j = 0;
for (int i = 0; i < n; ++i) {
char c = s.charAt(i);
cnt.put(c, cnt.getOrDefault(c, 0) + 1);
while (cnt.size() > k) {
char t = s.charAt(j);
cnt.put(t, cnt.getOrDefault(t, 0) - 1);
if (cnt.get(t) == 0) {
cnt.remove(t);
int l = 0;
char[] cs = s.toCharArray();
for (char c : cs) {
cnt.merge(c, 1, Integer::sum);
if (cnt.size() > k) {
if (cnt.merge(cs[l], -1, Integer::sum) == 0) {
cnt.remove(cs[l]);
}
++j;
++l;
}
ans = Math.max(ans, i - j + 1);
}
return ans;
return cs.length - l;
}
}
Loading
Loading