diff --git a/solution/2400-2499/2405.Optimal Partition of String/README.md b/solution/2400-2499/2405.Optimal Partition of String/README.md index e847070b034e3..7048499b8f9fc 100644 --- a/solution/2400-2499/2405.Optimal Partition of String/README.md +++ b/solution/2400-2499/2405.Optimal Partition of String/README.md @@ -64,11 +64,15 @@ tags: ### 方法一:贪心 -根据题意,每个子字符串应该尽可能长,且包含的字符唯一。我们只需要贪心地进行划分即可。 +根据题意,每个子字符串应该尽可能长,且包含的字符唯一,因此,我们只需要贪心地进行划分即可。 -过程中,可以用哈希表记录当前子字符串的所有字符,空间复杂度 $O(n)$;也可以使用一个数字,用位运算的方式记录字符,空间复杂度 $O(1)$。 +我们定义一个二进制整数 $\textit{mask}$ 来记录当前子字符串中出现的字符,其中 $\textit{mask}$ 的第 $i$ 位为 $1$ 表示第 $i$ 个字母已经出现过,为 $0$ 表示未出现过。另外,我们还需要一个变量 $\textit{ans}$ 来记录划分的子字符串个数,初始时 $\textit{ans} = 1$。 -时间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度。 +遍历字符串 $s$ 中的每个字符,对于每个字符 $c$,我们将其转换为 $0$ 到 $25$ 之间的整数 $x$,然后判断 $\textit{mask}$ 的第 $x$ 位是否为 $1$,如果为 $1$,说明当前字符 $c$ 与当前子字符串中的字符有重复,此时 $\textit{ans}$ 需要加 $1$,并将 $\textit{mask}$ 置为 $0$;否则,将 $\textit{mask}$ 的第 $x$ 位置为 $1$。然后,我们将 $\textit{mask}$ 更新为 $\textit{mask}$ 与 $2^x$ 的按位或结果。 + +最后,返回 $\textit{ans}$ 即可。 + +时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$。 @@ -77,13 +81,12 @@ tags: ```python class Solution: def partitionString(self, s: str) -> int: - ss = set() - ans = 1 - for c in s: - if c in ss: + ans, mask = 1, 0 + for x in map(lambda c: ord(c) - ord("a"), s): + if mask >> x & 1: ans += 1 - ss = set() - ss.add(c) + mask = 0 + mask |= 1 << x return ans ``` @@ -92,14 +95,14 @@ class Solution: ```java class Solution { public int partitionString(String s) { - Set ss = new HashSet<>(); - int ans = 1; - for (char c : s.toCharArray()) { - if (ss.contains(c)) { + int ans = 1, mask = 0; + for (int i = 0; i < s.length(); ++i) { + int x = s.charAt(i) - 'a'; + if ((mask >> x & 1) == 1) { ++ans; - ss.clear(); + mask = 0; } - ss.add(c); + mask |= 1 << x; } return ans; } @@ -112,14 +115,14 @@ class Solution { class Solution { public: int partitionString(string s) { - unordered_set ss; - int ans = 1; - for (char c : s) { - if (ss.count(c)) { + int ans = 1, mask = 0; + for (char& c : s) { + int x = c - 'a'; + if (mask >> x & 1) { ++ans; - ss.clear(); + mask = 0; } - ss.insert(c); + mask |= 1 << x; } return ans; } @@ -130,14 +133,14 @@ public: ```go func partitionString(s string) int { - ss := map[rune]bool{} - ans := 1 + ans, mask := 1, 0 for _, c := range s { - if ss[c] { + x := int(c - 'a') + if mask>>x&1 == 1 { ans++ - ss = map[rune]bool{} + mask = 0 } - ss[c] = true + mask |= 1 << x } return ans } @@ -147,35 +150,34 @@ func partitionString(s string) int { ```ts function partitionString(s: string): number { - const set = new Set(); - let res = 1; + let [ans, mask] = [1, 0]; for (const c of s) { - if (set.has(c)) { - res++; - set.clear(); + const x = c.charCodeAt(0) - 97; + if ((mask >> x) & 1) { + ++ans; + mask = 0; } - set.add(c); + mask |= 1 << x; } - return res; + return ans; } ``` #### Rust ```rust -use std::collections::HashSet; impl Solution { pub fn partition_string(s: String) -> i32 { - let mut set = HashSet::new(); - let mut res = 1; - for c in s.as_bytes().iter() { - if set.contains(c) { - res += 1; - set.clear(); + let mut ans = 1; + let mut mask = 0; + for x in s.chars().map(|c| (c as u8 - b'a') as u32) { + if mask >> x & 1 == 1 { + ans += 1; + mask = 0; } - set.insert(c); + mask |= 1 << x; } - res + ans } } ``` @@ -184,87 +186,4 @@ impl Solution { - - -### 方法二 - - - -#### Python3 - -```python -class Solution: - def partitionString(self, s: str) -> int: - ans, v = 1, 0 - for c in s: - i = ord(c) - ord('a') - if (v >> i) & 1: - v = 0 - ans += 1 - v |= 1 << i - return ans -``` - -#### Java - -```java -class Solution { - public int partitionString(String s) { - int v = 0; - int ans = 1; - for (char c : s.toCharArray()) { - int i = c - 'a'; - if (((v >> i) & 1) == 1) { - v = 0; - ++ans; - } - v |= 1 << i; - } - return ans; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int partitionString(string s) { - int ans = 1; - int v = 0; - for (char c : s) { - int i = c - 'a'; - if ((v >> i) & 1) { - v = 0; - ++ans; - } - v |= 1 << i; - } - return ans; - } -}; -``` - -#### Go - -```go -func partitionString(s string) int { - ans, v := 1, 0 - for _, c := range s { - i := int(c - 'a') - if v>>i&1 == 1 { - v = 0 - ans++ - } - v |= 1 << i - } - return ans -} -``` - - - - - diff --git a/solution/2400-2499/2405.Optimal Partition of String/README_EN.md b/solution/2400-2499/2405.Optimal Partition of String/README_EN.md index 196a381d382cc..e29aa6fae6df3 100644 --- a/solution/2400-2499/2405.Optimal Partition of String/README_EN.md +++ b/solution/2400-2499/2405.Optimal Partition of String/README_EN.md @@ -62,11 +62,15 @@ It can be shown that 4 is the minimum number of substrings needed. ### Solution 1: Greedy -According to the problem, each substring should be as long as possible and contain unique characters. We just need to partition greedily. +According to the problem description, each substring should be as long as possible and contain unique characters. Therefore, we can greedily partition the string. -During the process, we can use a hash table to record all characters in the current substring, with a space complexity of $O(n)$; or we can use a number to record characters using bitwise operations, with a space complexity of $O(1)$. +We define a binary integer $\textit{mask}$ to record the characters that have appeared in the current substring. The $i$-th bit of $\textit{mask}$ being $1$ indicates that the $i$-th letter has already appeared, and $0$ indicates that it has not appeared. Additionally, we need a variable $\textit{ans}$ to record the number of substrings, initially $\textit{ans} = 1$. -The time complexity is $O(n)$, where $n$ is the length of the string $s$. +Traverse each character in the string $s$. For each character $c$, convert it to an integer $x$ between $0$ and $25$, then check if the $x$-th bit of $\textit{mask}$ is $1$. If it is $1$, it means the current character $c$ is a duplicate in the current substring. In this case, increment $\textit{ans}$ by $1$ and reset $\textit{mask}$ to $0$. Otherwise, set the $x$-th bit of $\textit{mask}$ to $1$. Then, update $\textit{mask}$ to the bitwise OR result of $\textit{mask}$ and $2^x$. + +Finally, return $\textit{ans}$. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$. @@ -75,13 +79,12 @@ The time complexity is $O(n)$, where $n$ is the length of the string $s$. ```python class Solution: def partitionString(self, s: str) -> int: - ss = set() - ans = 1 - for c in s: - if c in ss: + ans, mask = 1, 0 + for x in map(lambda c: ord(c) - ord("a"), s): + if mask >> x & 1: ans += 1 - ss = set() - ss.add(c) + mask = 0 + mask |= 1 << x return ans ``` @@ -90,14 +93,14 @@ class Solution: ```java class Solution { public int partitionString(String s) { - Set ss = new HashSet<>(); - int ans = 1; - for (char c : s.toCharArray()) { - if (ss.contains(c)) { + int ans = 1, mask = 0; + for (int i = 0; i < s.length(); ++i) { + int x = s.charAt(i) - 'a'; + if ((mask >> x & 1) == 1) { ++ans; - ss.clear(); + mask = 0; } - ss.add(c); + mask |= 1 << x; } return ans; } @@ -110,14 +113,14 @@ class Solution { class Solution { public: int partitionString(string s) { - unordered_set ss; - int ans = 1; - for (char c : s) { - if (ss.count(c)) { + int ans = 1, mask = 0; + for (char& c : s) { + int x = c - 'a'; + if (mask >> x & 1) { ++ans; - ss.clear(); + mask = 0; } - ss.insert(c); + mask |= 1 << x; } return ans; } @@ -128,14 +131,14 @@ public: ```go func partitionString(s string) int { - ss := map[rune]bool{} - ans := 1 + ans, mask := 1, 0 for _, c := range s { - if ss[c] { + x := int(c - 'a') + if mask>>x&1 == 1 { ans++ - ss = map[rune]bool{} + mask = 0 } - ss[c] = true + mask |= 1 << x } return ans } @@ -145,35 +148,34 @@ func partitionString(s string) int { ```ts function partitionString(s: string): number { - const set = new Set(); - let res = 1; + let [ans, mask] = [1, 0]; for (const c of s) { - if (set.has(c)) { - res++; - set.clear(); + const x = c.charCodeAt(0) - 97; + if ((mask >> x) & 1) { + ++ans; + mask = 0; } - set.add(c); + mask |= 1 << x; } - return res; + return ans; } ``` #### Rust ```rust -use std::collections::HashSet; impl Solution { pub fn partition_string(s: String) -> i32 { - let mut set = HashSet::new(); - let mut res = 1; - for c in s.as_bytes().iter() { - if set.contains(c) { - res += 1; - set.clear(); + let mut ans = 1; + let mut mask = 0; + for x in s.chars().map(|c| (c as u8 - b'a') as u32) { + if mask >> x & 1 == 1 { + ans += 1; + mask = 0; } - set.insert(c); + mask |= 1 << x; } - res + ans } } ``` @@ -182,87 +184,4 @@ impl Solution { - - -### Solution 2 - - - -#### Python3 - -```python -class Solution: - def partitionString(self, s: str) -> int: - ans, v = 1, 0 - for c in s: - i = ord(c) - ord('a') - if (v >> i) & 1: - v = 0 - ans += 1 - v |= 1 << i - return ans -``` - -#### Java - -```java -class Solution { - public int partitionString(String s) { - int v = 0; - int ans = 1; - for (char c : s.toCharArray()) { - int i = c - 'a'; - if (((v >> i) & 1) == 1) { - v = 0; - ++ans; - } - v |= 1 << i; - } - return ans; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int partitionString(string s) { - int ans = 1; - int v = 0; - for (char c : s) { - int i = c - 'a'; - if ((v >> i) & 1) { - v = 0; - ++ans; - } - v |= 1 << i; - } - return ans; - } -}; -``` - -#### Go - -```go -func partitionString(s string) int { - ans, v := 1, 0 - for _, c := range s { - i := int(c - 'a') - if v>>i&1 == 1 { - v = 0 - ans++ - } - v |= 1 << i - } - return ans -} -``` - - - - - diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution.cpp b/solution/2400-2499/2405.Optimal Partition of String/Solution.cpp index b3f1fbbdc92d0..7d4afa0a8954b 100644 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution.cpp +++ b/solution/2400-2499/2405.Optimal Partition of String/Solution.cpp @@ -1,15 +1,15 @@ class Solution { public: int partitionString(string s) { - unordered_set ss; - int ans = 1; - for (char c : s) { - if (ss.count(c)) { + int ans = 1, mask = 0; + for (char& c : s) { + int x = c - 'a'; + if (mask >> x & 1) { ++ans; - ss.clear(); + mask = 0; } - ss.insert(c); + mask |= 1 << x; } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution.go b/solution/2400-2499/2405.Optimal Partition of String/Solution.go index 0550d6e0fc7ab..5376ce2c335d5 100644 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution.go +++ b/solution/2400-2499/2405.Optimal Partition of String/Solution.go @@ -1,12 +1,12 @@ func partitionString(s string) int { - ss := map[rune]bool{} - ans := 1 + ans, mask := 1, 0 for _, c := range s { - if ss[c] { + x := int(c - 'a') + if mask>>x&1 == 1 { ans++ - ss = map[rune]bool{} + mask = 0 } - ss[c] = true + mask |= 1 << x } return ans -} \ No newline at end of file +} diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution.java b/solution/2400-2499/2405.Optimal Partition of String/Solution.java index ddca7d757fbd9..7ee29a338c9d5 100644 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution.java +++ b/solution/2400-2499/2405.Optimal Partition of String/Solution.java @@ -1,14 +1,14 @@ class Solution { public int partitionString(String s) { - Set ss = new HashSet<>(); - int ans = 1; - for (char c : s.toCharArray()) { - if (ss.contains(c)) { + int ans = 1, mask = 0; + for (int i = 0; i < s.length(); ++i) { + int x = s.charAt(i) - 'a'; + if ((mask >> x & 1) == 1) { ++ans; - ss.clear(); + mask = 0; } - ss.add(c); + mask |= 1 << x; } return ans; } -} \ No newline at end of file +} diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution.py b/solution/2400-2499/2405.Optimal Partition of String/Solution.py index 44f216c5ad84a..f46f1a1e2be5d 100644 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution.py +++ b/solution/2400-2499/2405.Optimal Partition of String/Solution.py @@ -1,10 +1,9 @@ class Solution: def partitionString(self, s: str) -> int: - ss = set() - ans = 1 - for c in s: - if c in ss: + ans, mask = 1, 0 + for x in map(lambda c: ord(c) - ord("a"), s): + if mask >> x & 1: ans += 1 - ss = set() - ss.add(c) + mask = 0 + mask |= 1 << x return ans diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution.rs b/solution/2400-2499/2405.Optimal Partition of String/Solution.rs index be31be7348e31..327ddab46a6c5 100644 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution.rs +++ b/solution/2400-2499/2405.Optimal Partition of String/Solution.rs @@ -1,15 +1,14 @@ -use std::collections::HashSet; impl Solution { pub fn partition_string(s: String) -> i32 { - let mut set = HashSet::new(); - let mut res = 1; - for c in s.as_bytes().iter() { - if set.contains(c) { - res += 1; - set.clear(); + let mut ans = 1; + let mut mask = 0; + for x in s.chars().map(|c| (c as u8 - b'a') as u32) { + if mask >> x & 1 == 1 { + ans += 1; + mask = 0; } - set.insert(c); + mask |= 1 << x; } - res + ans } } diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution.ts b/solution/2400-2499/2405.Optimal Partition of String/Solution.ts index 12ca6d01032a4..998174642c05b 100644 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution.ts +++ b/solution/2400-2499/2405.Optimal Partition of String/Solution.ts @@ -1,12 +1,12 @@ function partitionString(s: string): number { - const set = new Set(); - let res = 1; + let [ans, mask] = [1, 0]; for (const c of s) { - if (set.has(c)) { - res++; - set.clear(); + const x = c.charCodeAt(0) - 97; + if ((mask >> x) & 1) { + ++ans; + mask = 0; } - set.add(c); + mask |= 1 << x; } - return res; + return ans; } diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution2.cpp b/solution/2400-2499/2405.Optimal Partition of String/Solution2.cpp deleted file mode 100644 index a0bef78cd437d..0000000000000 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution2.cpp +++ /dev/null @@ -1,16 +0,0 @@ -class Solution { -public: - int partitionString(string s) { - int ans = 1; - int v = 0; - for (char c : s) { - int i = c - 'a'; - if ((v >> i) & 1) { - v = 0; - ++ans; - } - v |= 1 << i; - } - return ans; - } -}; \ No newline at end of file diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution2.go b/solution/2400-2499/2405.Optimal Partition of String/Solution2.go deleted file mode 100644 index 0ed4084c4d890..0000000000000 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution2.go +++ /dev/null @@ -1,12 +0,0 @@ -func partitionString(s string) int { - ans, v := 1, 0 - for _, c := range s { - i := int(c - 'a') - if v>>i&1 == 1 { - v = 0 - ans++ - } - v |= 1 << i - } - return ans -} \ No newline at end of file diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution2.java b/solution/2400-2499/2405.Optimal Partition of String/Solution2.java deleted file mode 100644 index 89683b1b9fe16..0000000000000 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution2.java +++ /dev/null @@ -1,15 +0,0 @@ -class Solution { - public int partitionString(String s) { - int v = 0; - int ans = 1; - for (char c : s.toCharArray()) { - int i = c - 'a'; - if (((v >> i) & 1) == 1) { - v = 0; - ++ans; - } - v |= 1 << i; - } - return ans; - } -} \ No newline at end of file diff --git a/solution/2400-2499/2405.Optimal Partition of String/Solution2.py b/solution/2400-2499/2405.Optimal Partition of String/Solution2.py deleted file mode 100644 index df3265ccba350..0000000000000 --- a/solution/2400-2499/2405.Optimal Partition of String/Solution2.py +++ /dev/null @@ -1,10 +0,0 @@ -class Solution: - def partitionString(self, s: str) -> int: - ans, v = 1, 0 - for c in s: - i = ord(c) - ord('a') - if (v >> i) & 1: - v = 0 - ans += 1 - v |= 1 << i - return ans