diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md index 0a34e8470465a..9d5d399aca7f6 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md @@ -26,7 +26,7 @@ tags:
 输入: s = "abcabcbb"
-输出: 3 
+输出: 3
 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
 
@@ -62,26 +62,15 @@ tags: -### 方法一:双指针 + 哈希表 - -定义一个哈希表记录当前窗口内出现的字符,记 $i$ 和 $j$ 分别表示不重复子串的开始位置和结束位置,无重复字符子串的最大长度记为 `ans`。 +### 方法一:滑动窗口 -遍历字符串 `s` 的每个字符 $s[j]$,我们记为 $c$。若 $s[i..j-1]$ 窗口内存在 $c$,则 $i$ 循环向右移动,更新哈希表,直至 $s[i..j-1]$ 窗口不存在 `c`,循环结束。将 `c` 加入哈希表中,此时 $s[i..j]$ 窗口内不含重复元素,更新 `ans` 的最大值。 +我们可以用两个指针 $l$ 和 $r$ 维护一个滑动窗口,使其始终满足窗口内没有重复字符,初始时 $l$ 和 $r$ 都指向字符串的第一个字符。用一个哈希表或者长度为 $128$ 的数组 $\textit{cnt}$ 来记录每个字符出现的次数,其中 $\textit{cnt}[c]$ 表示字符 $c$ 出现的次数。 -最后返回 `ans` 即可。 +接下来,我们依次移动右指针 $r$,每次移动时,将 $\textit{cnt}[s[r]]$ 的值加 $1$,然后判断当前窗口 $[l, r]$ 内 $\textit{cnt}[s[r]]$ 是否大于 $1$,如果大于 $1$,说明当前窗口内有重复字符,我们需要移动左指针 $l$,直到窗口内没有重复字符为止。然后,我们更新答案 $\textit{ans} = \max(\textit{ans}, r - l + 1)$。 -时间复杂度 $O(n)$,其中 $n$ 表示字符串 `s` 的长度。 +最终,我们返回答案 $\textit{ans}$ 即可。 -双指针算法模板: - -```java -for (int i = 0, j = 0; i < n; ++i) { - while (j < i && check(j, i)) { - ++j; - } - // 具体问题的逻辑 -} -``` +时间复杂度 $O(n)$,其中 $n$ 为字符串的长度。空间复杂度 $O(|\Sigma|)$,其中 $\Sigma$ 表示字符集,这里 $\Sigma$ 的大小为 $128$。 @@ -90,14 +79,14 @@ for (int i = 0, j = 0; i < n; ++i) { ```python class Solution: def lengthOfLongestSubstring(self, s: str) -> int: - ss = set() - ans = i = 0 - for j, c in enumerate(s): - while c in ss: - ss.remove(s[i]) - i += 1 - ss.add(c) - ans = max(ans, j - i + 1) + cnt = Counter() + ans = l = 0 + for r, c in enumerate(s): + cnt[c] += 1 + while cnt[c] > 1: + cnt[s[l]] -= 1 + l += 1 + ans = max(ans, r - l + 1) return ans ``` @@ -106,15 +95,15 @@ class Solution: ```java class Solution { public int lengthOfLongestSubstring(String s) { - boolean[] ss = new boolean[128]; - int ans = 0; - for (int i = 0, j = 0; j < s.length(); ++j) { - char c = s.charAt(j); - while (ss[c]) { - ss[s.charAt(i++)] = false; + int[] cnt = new int[128]; + int ans = 0, n = s.length(); + for (int l = 0, r = 0; r < n; ++r) { + char c = s.charAt(r); + ++cnt[c]; + while (cnt[c] > 1) { + --cnt[s.charAt(l++)]; } - ss[c] = true; - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; } @@ -127,14 +116,14 @@ class Solution { class Solution { public: int lengthOfLongestSubstring(string s) { - bool ss[128]{}; - int ans = 0; - for (int i = 0, j = 0; j < s.size(); ++j) { - while (ss[s[j]]) { - ss[s[i++]] = false; + int cnt[128]{}; + int ans = 0, n = s.size(); + for (int l = 0, r = 0; r < n; ++r) { + ++cnt[s[r]]; + while (cnt[s[r]] > 1) { + --cnt[s[l++]]; } - ss[s[j]] = true; - ans = max(ans, j - i + 1); + ans = max(ans, r - l + 1); } return ans; } @@ -145,14 +134,15 @@ public: ```go func lengthOfLongestSubstring(s string) (ans int) { - ss := [128]bool{} - for i, j := 0, 0; j < len(s); j++ { - for ss[s[j]] { - ss[s[i]] = false - i++ + cnt := [128]int{} + l := 0 + for r, c := range s { + cnt[c]++ + for cnt[c] > 1 { + cnt[s[l]]-- + l++ } - ss[s[j]] = true - ans = max(ans, j-i+1) + ans = max(ans, r-l+1) } return } @@ -163,13 +153,15 @@ func lengthOfLongestSubstring(s string) (ans int) { ```ts function lengthOfLongestSubstring(s: string): number { let ans = 0; - const ss: Set = new Set(); - for (let i = 0, j = 0; j < s.length; ++j) { - while (ss.has(s[j])) { - ss.delete(s[i++]); + const cnt = new Map(); + const n = s.length; + for (let l = 0, r = 0; r < n; ++r) { + cnt.set(s[r], (cnt.get(s[r]) || 0) + 1); + while (cnt.get(s[r])! > 1) { + cnt.set(s[l], cnt.get(s[l])! - 1); + ++l; } - ss.add(s[j]); - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; } @@ -178,24 +170,22 @@ function lengthOfLongestSubstring(s: string): number { #### Rust ```rust -use std::collections::HashSet; - impl Solution { pub fn length_of_longest_substring(s: String) -> i32 { - let s = s.as_bytes(); - let mut ss = HashSet::new(); - let mut i = 0; - s.iter() - .map(|c| { - while ss.contains(&c) { - ss.remove(&s[i]); - i += 1; - } - ss.insert(c); - ss.len() - }) - .max() - .unwrap_or(0) as i32 + let mut cnt = [0; 128]; + let mut ans = 0; + let mut l = 0; + let chars: Vec = s.chars().collect(); + let n = chars.len(); + for (r, &c) in chars.iter().enumerate() { + cnt[c as usize] += 1; + while cnt[c as usize] > 1 { + cnt[chars[l] as usize] -= 1; + l += 1; + } + ans = ans.max((r - l + 1) as i32); + } + ans } } ``` @@ -209,13 +199,15 @@ impl Solution { */ var lengthOfLongestSubstring = function (s) { let ans = 0; - const ss = new Set(); - for (let i = 0, j = 0; j < s.length; ++j) { - while (ss.has(s[j])) { - ss.delete(s[i++]); + const n = s.length; + const cnt = new Map(); + for (let l = 0, r = 0; r < n; ++r) { + cnt.set(s[r], (cnt.get(s[r]) || 0) + 1); + while (cnt.get(s[r]) > 1) { + cnt.set(s[l], cnt.get(s[l]) - 1); + ++l; } - ss.add(s[j]); - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; }; @@ -226,14 +218,15 @@ var lengthOfLongestSubstring = function (s) { ```cs public class Solution { public int LengthOfLongestSubstring(string s) { + int n = s.Length; int ans = 0; - var ss = new HashSet(); - for (int i = 0, j = 0; j < s.Length; ++j) { - while (ss.Contains(s[j])) { - ss.Remove(s[i++]); + var cnt = new int[128]; + for (int l = 0, r = 0; r < n; ++r) { + ++cnt[s[r]]; + while (cnt[s[r]] > 1) { + --cnt[s[l++]]; } - ss.Add(s[j]); - ans = Math.Max(ans, j - i + 1); + ans = Math.Max(ans, r - l + 1); } return ans; } @@ -244,19 +237,18 @@ public class Solution { ```php class Solution { - /** - * @param String $s - * @return Integer - */ function lengthOfLongestSubstring($s) { + $n = strlen($s); $ans = 0; - $ss = []; - for ($i = 0, $j = 0; $j < strlen($s); ++$j) { - while (in_array($s[$j], $ss)) { - unset($ss[array_search($s[$i++], $ss)]); + $cnt = array_fill(0, 128, 0); + $l = 0; + for ($r = 0; $r < $n; ++$r) { + $cnt[ord($s[$r])]++; + while ($cnt[ord($s[$r])] > 1) { + $cnt[ord($s[$l])]--; + $l++; } - $ss[] = $s[$j]; - $ans = max($ans, $j - $i + 1); + $ans = max($ans, $r - $l + 1); } return $ans; } @@ -268,62 +260,40 @@ class Solution { ```swift class Solution { func lengthOfLongestSubstring(_ s: String) -> Int { - var map = [Character: Int]() - var currentStartingIndex = 0 - var i = 0 - var maxLength = 0 - for char in s { - if map[char] != nil { - if map[char]! >= currentStartingIndex { - maxLength = max(maxLength, i - currentStartingIndex) - currentStartingIndex = map[char]! + 1 - } + let n = s.count + var ans = 0 + var cnt = [Int](repeating: 0, count: 128) + var l = 0 + let sArray = Array(s) + for r in 0.. 1 { + cnt[Int(sArray[l].asciiValue!)] -= 1 + l += 1 } - map[char] = i - i += 1 + ans = max(ans, r - l + 1) } - return max(maxLength, i - currentStartingIndex) + return ans } } ``` -#### Nim - -```nim -proc lengthOfLongestSubstring(s: string): int = - var - i = 0 - j = 0 - res = 0 - literals: set[char] = {} - - while i < s.len: - while s[i] in literals: - if s[j] in literals: - excl(literals, s[j]) - j += 1 - literals.incl(s[i]) # Uniform Function Call Syntax f(x) = x.f - res = max(res, i - j + 1) - i += 1 - - result = res # result has the default return value -``` - #### Kotlin ```kotlin class Solution { fun lengthOfLongestSubstring(s: String): Int { - var char_set = BooleanArray(128) - var left = 0 + val n = s.length var ans = 0 - s.forEachIndexed { right, c -> - while (char_set[c.code]) { - char_set[s[left].code] = false - left++ + val cnt = IntArray(128) + var l = 0 + for (r in 0 until n) { + cnt[s[r].toInt()]++ + while (cnt[s[r].toInt()] > 1) { + cnt[s[l].toInt()]-- + l++ } - char_set[c.code] = true - ans = Math.max(ans, right - left + 1) + ans = Math.max(ans, r - l + 1) } return ans } diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md index 7218d6526623c..c8302cd9b1aab 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md @@ -60,26 +60,15 @@ Notice that the answer must be a substring, "pwke" is a subsequence an -### Solution 1: Two pointers + Hash Table +### Solution 1: Sliding Window -Define a hash table to record the characters in the current window. Let $i$ and $j$ represent the start and end positions of the non-repeating substring, respectively. The length of the longest non-repeating substring is recorded by `ans`. +We can use two pointers $l$ and $r$ to maintain a sliding window that always satisfies the condition of having no repeating characters within the window. Initially, both $l$ and $r$ point to the first character of the string. We use a hash table or an array of length $128$ called $\textit{cnt}$ to record the number of occurrences of each character, where $\textit{cnt}[c]$ represents the number of occurrences of character $c$. -For each character $s[j]$ in the string `s`, we call it $c$. If $c$ exists in the window $s[i..j-1]$, we move $i$ to the right until $s[i..j-1]$ does not contain `c`. Then we add `c` to the hash table. At this time, the window $s[i..j]$ does not contain repeated elements, and we update the maximum value of `ans`. +Next, we move the right pointer $r$ one step at a time. Each time we move it, we increment the value of $\textit{cnt}[s[r]]$ by $1$, and then check if the value of $\textit{cnt}[s[r]]$ is greater than $1$ within the current window $[l, r]$. If it is greater than $1$, it means there are repeating characters within the current window, and we need to move the left pointer $l$ until there are no repeating characters within the window. Then, we update the answer $\textit{ans} = \max(\textit{ans}, r - l + 1)$. -Finally, return `ans`. +Finally, we return the answer $\textit{ans}$. -The time complexity is $O(n)$, where $n$ represents the length of the string `s`. - -Two pointers algorithm template: - -```java -for (int i = 0, j = 0; i < n; ++i) { - while (j < i && check(j, i)) { - ++j; - } - // logic of specific problem -} -``` +The time complexity is $O(n)$, where $n$ is the length of the string. The space complexity is $O(|\Sigma|)$, where $\Sigma$ represents the character set, and the size of $\Sigma$ is $128$. @@ -88,14 +77,14 @@ for (int i = 0, j = 0; i < n; ++i) { ```python class Solution: def lengthOfLongestSubstring(self, s: str) -> int: - ss = set() - ans = i = 0 - for j, c in enumerate(s): - while c in ss: - ss.remove(s[i]) - i += 1 - ss.add(c) - ans = max(ans, j - i + 1) + cnt = Counter() + ans = l = 0 + for r, c in enumerate(s): + cnt[c] += 1 + while cnt[c] > 1: + cnt[s[l]] -= 1 + l += 1 + ans = max(ans, r - l + 1) return ans ``` @@ -104,15 +93,15 @@ class Solution: ```java class Solution { public int lengthOfLongestSubstring(String s) { - boolean[] ss = new boolean[128]; - int ans = 0; - for (int i = 0, j = 0; j < s.length(); ++j) { - char c = s.charAt(j); - while (ss[c]) { - ss[s.charAt(i++)] = false; + int[] cnt = new int[128]; + int ans = 0, n = s.length(); + for (int l = 0, r = 0; r < n; ++r) { + char c = s.charAt(r); + ++cnt[c]; + while (cnt[c] > 1) { + --cnt[s.charAt(l++)]; } - ss[c] = true; - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; } @@ -125,14 +114,14 @@ class Solution { class Solution { public: int lengthOfLongestSubstring(string s) { - bool ss[128]{}; - int ans = 0; - for (int i = 0, j = 0; j < s.size(); ++j) { - while (ss[s[j]]) { - ss[s[i++]] = false; + int cnt[128]{}; + int ans = 0, n = s.size(); + for (int l = 0, r = 0; r < n; ++r) { + ++cnt[s[r]]; + while (cnt[s[r]] > 1) { + --cnt[s[l++]]; } - ss[s[j]] = true; - ans = max(ans, j - i + 1); + ans = max(ans, r - l + 1); } return ans; } @@ -143,14 +132,15 @@ public: ```go func lengthOfLongestSubstring(s string) (ans int) { - ss := [128]bool{} - for i, j := 0, 0; j < len(s); j++ { - for ss[s[j]] { - ss[s[i]] = false - i++ + cnt := [128]int{} + l := 0 + for r, c := range s { + cnt[c]++ + for cnt[c] > 1 { + cnt[s[l]]-- + l++ } - ss[s[j]] = true - ans = max(ans, j-i+1) + ans = max(ans, r-l+1) } return } @@ -161,13 +151,15 @@ func lengthOfLongestSubstring(s string) (ans int) { ```ts function lengthOfLongestSubstring(s: string): number { let ans = 0; - const ss: Set = new Set(); - for (let i = 0, j = 0; j < s.length; ++j) { - while (ss.has(s[j])) { - ss.delete(s[i++]); + const cnt = new Map(); + const n = s.length; + for (let l = 0, r = 0; r < n; ++r) { + cnt.set(s[r], (cnt.get(s[r]) || 0) + 1); + while (cnt.get(s[r])! > 1) { + cnt.set(s[l], cnt.get(s[l])! - 1); + ++l; } - ss.add(s[j]); - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; } @@ -176,24 +168,22 @@ function lengthOfLongestSubstring(s: string): number { #### Rust ```rust -use std::collections::HashSet; - impl Solution { pub fn length_of_longest_substring(s: String) -> i32 { - let s = s.as_bytes(); - let mut ss = HashSet::new(); - let mut i = 0; - s.iter() - .map(|c| { - while ss.contains(&c) { - ss.remove(&s[i]); - i += 1; - } - ss.insert(c); - ss.len() - }) - .max() - .unwrap_or(0) as i32 + let mut cnt = [0; 128]; + let mut ans = 0; + let mut l = 0; + let chars: Vec = s.chars().collect(); + let n = chars.len(); + for (r, &c) in chars.iter().enumerate() { + cnt[c as usize] += 1; + while cnt[c as usize] > 1 { + cnt[chars[l] as usize] -= 1; + l += 1; + } + ans = ans.max((r - l + 1) as i32); + } + ans } } ``` @@ -207,13 +197,15 @@ impl Solution { */ var lengthOfLongestSubstring = function (s) { let ans = 0; - const ss = new Set(); - for (let i = 0, j = 0; j < s.length; ++j) { - while (ss.has(s[j])) { - ss.delete(s[i++]); + const n = s.length; + const cnt = new Map(); + for (let l = 0, r = 0; r < n; ++r) { + cnt.set(s[r], (cnt.get(s[r]) || 0) + 1); + while (cnt.get(s[r]) > 1) { + cnt.set(s[l], cnt.get(s[l]) - 1); + ++l; } - ss.add(s[j]); - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; }; @@ -224,14 +216,15 @@ var lengthOfLongestSubstring = function (s) { ```cs public class Solution { public int LengthOfLongestSubstring(string s) { + int n = s.Length; int ans = 0; - var ss = new HashSet(); - for (int i = 0, j = 0; j < s.Length; ++j) { - while (ss.Contains(s[j])) { - ss.Remove(s[i++]); + var cnt = new int[128]; + for (int l = 0, r = 0; r < n; ++r) { + ++cnt[s[r]]; + while (cnt[s[r]] > 1) { + --cnt[s[l++]]; } - ss.Add(s[j]); - ans = Math.Max(ans, j - i + 1); + ans = Math.Max(ans, r - l + 1); } return ans; } @@ -242,19 +235,18 @@ public class Solution { ```php class Solution { - /** - * @param String $s - * @return Integer - */ function lengthOfLongestSubstring($s) { + $n = strlen($s); $ans = 0; - $ss = []; - for ($i = 0, $j = 0; $j < strlen($s); ++$j) { - while (in_array($s[$j], $ss)) { - unset($ss[array_search($s[$i++], $ss)]); + $cnt = array_fill(0, 128, 0); + $l = 0; + for ($r = 0; $r < $n; ++$r) { + $cnt[ord($s[$r])]++; + while ($cnt[ord($s[$r])] > 1) { + $cnt[ord($s[$l])]--; + $l++; } - $ss[] = $s[$j]; - $ans = max($ans, $j - $i + 1); + $ans = max($ans, $r - $l + 1); } return $ans; } @@ -266,62 +258,40 @@ class Solution { ```swift class Solution { func lengthOfLongestSubstring(_ s: String) -> Int { - var map = [Character: Int]() - var currentStartingIndex = 0 - var i = 0 - var maxLength = 0 - for char in s { - if map[char] != nil { - if map[char]! >= currentStartingIndex { - maxLength = max(maxLength, i - currentStartingIndex) - currentStartingIndex = map[char]! + 1 - } + let n = s.count + var ans = 0 + var cnt = [Int](repeating: 0, count: 128) + var l = 0 + let sArray = Array(s) + for r in 0.. 1 { + cnt[Int(sArray[l].asciiValue!)] -= 1 + l += 1 } - map[char] = i - i += 1 + ans = max(ans, r - l + 1) } - return max(maxLength, i - currentStartingIndex) + return ans } } ``` -#### Nim - -```nim -proc lengthOfLongestSubstring(s: string): int = - var - i = 0 - j = 0 - res = 0 - literals: set[char] = {} - - while i < s.len: - while s[i] in literals: - if s[j] in literals: - excl(literals, s[j]) - j += 1 - literals.incl(s[i]) # Uniform Function Call Syntax f(x) = x.f - res = max(res, i - j + 1) - i += 1 - - result = res # result has the default return value -``` - #### Kotlin ```kotlin class Solution { fun lengthOfLongestSubstring(s: String): Int { - var char_set = BooleanArray(128) - var left = 0 + val n = s.length var ans = 0 - s.forEachIndexed { right, c -> - while (char_set[c.code]) { - char_set[s[left].code] = false - left++ + val cnt = IntArray(128) + var l = 0 + for (r in 0 until n) { + cnt[s[r].toInt()]++ + while (cnt[s[r].toInt()] > 1) { + cnt[s[l].toInt()]-- + l++ } - char_set[c.code] = true - ans = Math.max(ans, right - left + 1) + ans = Math.max(ans, r - l + 1) } return ans } diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cpp b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cpp index 980f98df2cc44..549f59f0ae8b7 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cpp +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cpp @@ -1,15 +1,15 @@ class Solution { public: int lengthOfLongestSubstring(string s) { - bool ss[128]{}; - int ans = 0; - for (int i = 0, j = 0; j < s.size(); ++j) { - while (ss[s[j]]) { - ss[s[i++]] = false; + int cnt[128]{}; + int ans = 0, n = s.size(); + for (int l = 0, r = 0; r < n; ++r) { + ++cnt[s[r]]; + while (cnt[s[r]] > 1) { + --cnt[s[l++]]; } - ss[s[j]] = true; - ans = max(ans, j - i + 1); + ans = max(ans, r - l + 1); } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cs b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cs index 2c29e34899025..044baded41e3a 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cs +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cs @@ -1,13 +1,14 @@ public class Solution { public int LengthOfLongestSubstring(string s) { + int n = s.Length; int ans = 0; - var ss = new HashSet(); - for (int i = 0, j = 0; j < s.Length; ++j) { - while (ss.Contains(s[j])) { - ss.Remove(s[i++]); + var cnt = new int[128]; + for (int l = 0, r = 0; r < n; ++r) { + ++cnt[s[r]]; + while (cnt[s[r]] > 1) { + --cnt[s[l++]]; } - ss.Add(s[j]); - ans = Math.Max(ans, j - i + 1); + ans = Math.Max(ans, r - l + 1); } return ans; } diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.go b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.go index 68104afd448ff..365301a1ce97f 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.go +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.go @@ -1,12 +1,13 @@ func lengthOfLongestSubstring(s string) (ans int) { - ss := [128]bool{} - for i, j := 0, 0; j < len(s); j++ { - for ss[s[j]] { - ss[s[i]] = false - i++ + cnt := [128]int{} + l := 0 + for r, c := range s { + cnt[c]++ + for cnt[c] > 1 { + cnt[s[l]]-- + l++ } - ss[s[j]] = true - ans = max(ans, j-i+1) + ans = max(ans, r-l+1) } return -} \ No newline at end of file +} diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java index 28dda65b2442d..574f3c62a27e8 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java @@ -1,15 +1,15 @@ class Solution { public int lengthOfLongestSubstring(String s) { - boolean[] ss = new boolean[128]; - int ans = 0; - for (int i = 0, j = 0; j < s.length(); ++j) { - char c = s.charAt(j); - while (ss[c]) { - ss[s.charAt(i++)] = false; + int[] cnt = new int[128]; + int ans = 0, n = s.length(); + for (int l = 0, r = 0; r < n; ++r) { + char c = s.charAt(r); + ++cnt[c]; + while (cnt[c] > 1) { + --cnt[s.charAt(l++)]; } - ss[c] = true; - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; } -} \ No newline at end of file +} diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.js b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.js index d87d290b2cfb3..16f64428d105f 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.js +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.js @@ -4,13 +4,15 @@ */ var lengthOfLongestSubstring = function (s) { let ans = 0; - const ss = new Set(); - for (let i = 0, j = 0; j < s.length; ++j) { - while (ss.has(s[j])) { - ss.delete(s[i++]); + const n = s.length; + const cnt = new Map(); + for (let l = 0, r = 0; r < n; ++r) { + cnt.set(s[r], (cnt.get(s[r]) || 0) + 1); + while (cnt.get(s[r]) > 1) { + cnt.set(s[l], cnt.get(s[l]) - 1); + ++l; } - ss.add(s[j]); - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; }; diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.kt b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.kt index f98e101a2f826..82cba82a59d3e 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.kt +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.kt @@ -1,15 +1,16 @@ class Solution { fun lengthOfLongestSubstring(s: String): Int { - var char_set = BooleanArray(128) - var left = 0 + val n = s.length var ans = 0 - s.forEachIndexed { right, c -> - while (char_set[c.code]) { - char_set[s[left].code] = false - left++ + val cnt = IntArray(128) + var l = 0 + for (r in 0 until n) { + cnt[s[r].toInt()]++ + while (cnt[s[r].toInt()] > 1) { + cnt[s[l].toInt()]-- + l++ } - char_set[c.code] = true - ans = Math.max(ans, right - left + 1) + ans = Math.max(ans, r - l + 1) } return ans } diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.nim b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.nim deleted file mode 100644 index 1275a35bfbee6..0000000000000 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.nim +++ /dev/null @@ -1,17 +0,0 @@ -proc lengthOfLongestSubstring(s: string): int = - var - i = 0 - j = 0 - res = 0 - literals: set[char] = {} - - while i < s.len: - while s[i] in literals: - if s[j] in literals: - excl(literals, s[j]) - j += 1 - literals.incl(s[i]) # Uniform Function Call Syntax f(x) = x.f - res = max(res, i - j + 1) - i += 1 - - result = res # result has the default return value diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.php b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.php index d51d37abe0e51..af9ebc954a1d7 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.php +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.php @@ -1,18 +1,17 @@ class Solution { - /** - * @param String $s - * @return Integer - */ function lengthOfLongestSubstring($s) { + $n = strlen($s); $ans = 0; - $ss = []; - for ($i = 0, $j = 0; $j < strlen($s); ++$j) { - while (in_array($s[$j], $ss)) { - unset($ss[array_search($s[$i++], $ss)]); + $cnt = array_fill(0, 128, 0); + $l = 0; + for ($r = 0; $r < $n; ++$r) { + $cnt[ord($s[$r])]++; + while ($cnt[ord($s[$r])] > 1) { + $cnt[ord($s[$l])]--; + $l++; } - $ss[] = $s[$j]; - $ans = max($ans, $j - $i + 1); + $ans = max($ans, $r - $l + 1); } return $ans; } -} \ No newline at end of file +} diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.py b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.py index 752e44282faee..828f12c0e90c7 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.py +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.py @@ -1,11 +1,11 @@ class Solution: def lengthOfLongestSubstring(self, s: str) -> int: - ss = set() - ans = i = 0 - for j, c in enumerate(s): - while c in ss: - ss.remove(s[i]) - i += 1 - ss.add(c) - ans = max(ans, j - i + 1) + cnt = Counter() + ans = l = 0 + for r, c in enumerate(s): + cnt[c] += 1 + while cnt[c] > 1: + cnt[s[l]] -= 1 + l += 1 + ans = max(ans, r - l + 1) return ans diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.rs b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.rs index 64e43f86096f5..ca4557f31fda6 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.rs +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.rs @@ -1,20 +1,18 @@ -use std::collections::HashSet; - impl Solution { pub fn length_of_longest_substring(s: String) -> i32 { - let s = s.as_bytes(); - let mut ss = HashSet::new(); - let mut i = 0; - s.iter() - .map(|c| { - while ss.contains(&c) { - ss.remove(&s[i]); - i += 1; - } - ss.insert(c); - ss.len() - }) - .max() - .unwrap_or(0) as i32 + let mut cnt = [0; 128]; + let mut ans = 0; + let mut l = 0; + let chars: Vec = s.chars().collect(); + let n = chars.len(); + for (r, &c) in chars.iter().enumerate() { + cnt[c as usize] += 1; + while cnt[c as usize] > 1 { + cnt[chars[l] as usize] -= 1; + l += 1; + } + ans = ans.max((r - l + 1) as i32); + } + ans } } diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.swift b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.swift index 02462178bdfd5..672a8f0f20787 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.swift +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.swift @@ -1,19 +1,18 @@ class Solution { func lengthOfLongestSubstring(_ s: String) -> Int { - var map = [Character: Int]() - var currentStartingIndex = 0 - var i = 0 - var maxLength = 0 - for char in s { - if map[char] != nil { - if map[char]! >= currentStartingIndex { - maxLength = max(maxLength, i - currentStartingIndex) - currentStartingIndex = map[char]! + 1 - } + let n = s.count + var ans = 0 + var cnt = [Int](repeating: 0, count: 128) + var l = 0 + let sArray = Array(s) + for r in 0.. 1 { + cnt[Int(sArray[l].asciiValue!)] -= 1 + l += 1 } - map[char] = i - i += 1 + ans = max(ans, r - l + 1) } - return max(maxLength, i - currentStartingIndex) + return ans } } diff --git a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.ts b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.ts index 6f4d8610c0bb0..f37a5ffaa95b6 100644 --- a/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.ts +++ b/solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.ts @@ -1,12 +1,14 @@ function lengthOfLongestSubstring(s: string): number { let ans = 0; - const ss: Set = new Set(); - for (let i = 0, j = 0; j < s.length; ++j) { - while (ss.has(s[j])) { - ss.delete(s[i++]); + const cnt = new Map(); + const n = s.length; + for (let l = 0, r = 0; r < n; ++r) { + cnt.set(s[r], (cnt.get(s[r]) || 0) + 1); + while (cnt.get(s[r])! > 1) { + cnt.set(s[l], cnt.get(s[l])! - 1); + ++l; } - ss.add(s[j]); - ans = Math.max(ans, j - i + 1); + ans = Math.max(ans, r - l + 1); } return ans; }