diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README.md b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README.md index 17a147e98aeae..3cb82b49879c6 100644 --- a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README.md +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README.md @@ -88,7 +88,13 @@ tags: -### 方法一 +### 方法一:哈希表 + 位运算 + +我们注意到,题目中给定的字符串只包含小写字母,并且每个字符串的字母至多出现一次。因此,我们可以用一个长度为 $26$ 的二进制数表示一个字符串,其中第 $i$ 位为 $1$ 表示字符串中包含第 $i$ 个小写字母,为 $0$ 表示字符串中不包含第 $i$ 个小写字母。 + +我们可以将字符串数组 $\text{startWords}$ 中的每个字符串转换为一个二进制数,并将这些二进制数存储到一个集合 $\text{s}$ 中。对于字符串数组 $\text{targetWords}$ 中的每个字符串,我们首先将其转换为一个二进制数,然后枚举这个字符串中的每个字母,将这个字母从二进制数中去掉,再检查是否存在一个二进制数在集合 $\text{s}$ 中,使得这个二进制数与去掉的字母的二进制数的异或结果在集合 $\text{s}$ 中,如果存在,那么这个字符串可以由 $\text{startWords}$ 中的某个字符串执行转换操作获得,答案加一。然后我们跳过这个字符串,继续处理下一个字符串。 + +时间复杂度 $O(n \times |\Sigma|)$,空间复杂度 $O(n)$。其中 $n$ 为字符串数组 $\text{targetWords}$ 的长度,而 $|\Sigma|$ 为字符串中的字符集大小,本题中 $|\Sigma| = 26$。 @@ -97,21 +103,12 @@ tags: ```python class Solution: def wordCount(self, startWords: List[str], targetWords: List[str]) -> int: - s = set() - for word in startWords: - mask = 0 - for c in word: - mask |= 1 << (ord(c) - ord('a')) - s.add(mask) - + s = {sum(1 << (ord(c) - 97) for c in w) for w in startWords} ans = 0 - for word in targetWords: - mask = 0 - for c in word: - mask |= 1 << (ord(c) - ord('a')) - for c in word: - t = mask ^ (1 << (ord(c) - ord('a'))) - if t in s: + for w in targetWords: + x = sum(1 << (ord(c) - 97) for c in w) + for c in w: + if x ^ (1 << (ord(c) - 97)) in s: ans += 1 break return ans @@ -121,25 +118,23 @@ class Solution: ```java class Solution { - public int wordCount(String[] startWords, String[] targetWords) { Set s = new HashSet<>(); - for (String word : startWords) { - int mask = 0; - for (char c : word.toCharArray()) { - mask |= (1 << (c - 'a')); + for (var w : startWords) { + int x = 0; + for (var c : w.toCharArray()) { + x |= 1 << (c - 'a'); } - s.add(mask); + s.add(x); } int ans = 0; - for (String word : targetWords) { - int mask = 0; - for (char c : word.toCharArray()) { - mask |= (1 << (c - 'a')); + for (var w : targetWords) { + int x = 0; + for (var c : w.toCharArray()) { + x |= 1 << (c - 'a'); } - for (char c : word.toCharArray()) { - int t = mask ^ (1 << (c - 'a')); - if (s.contains(t)) { + for (var c : w.toCharArray()) { + if (s.contains(x ^ (1 << (c - 'a')))) { ++ans; break; } @@ -157,20 +152,21 @@ class Solution { public: int wordCount(vector& startWords, vector& targetWords) { unordered_set s; - for (auto& word : startWords) { - int mask = 0; - for (char c : word) - mask |= (1 << (c - 'a')); - s.insert(mask); + for (auto& w : startWords) { + int x = 0; + for (char c : w) { + x |= 1 << (c - 'a'); + } + s.insert(x); } int ans = 0; - for (auto& word : targetWords) { - int mask = 0; - for (char c : word) - mask |= (1 << (c - 'a')); - for (char c : word) { - int t = mask ^ (1 << (c - 'a')); - if (s.count(t)) { + for (auto& w : targetWords) { + int x = 0; + for (char c : w) { + x |= 1 << (c - 'a'); + } + for (char c : w) { + if (s.contains(x ^ (1 << (c - 'a')))) { ++ans; break; } @@ -184,30 +180,57 @@ public: #### Go ```go -func wordCount(startWords []string, targetWords []string) int { - s := make(map[int]bool) - for _, word := range startWords { - mask := 0 - for _, c := range word { - mask |= (1 << (c - 'a')) +func wordCount(startWords []string, targetWords []string) (ans int) { + s := map[int]bool{} + for _, w := range startWords { + x := 0 + for _, c := range w { + x |= 1 << (c - 'a') } - s[mask] = true + s[x] = true } - ans := 0 - for _, word := range targetWords { - mask := 0 - for _, c := range word { - mask |= (1 << (c - 'a')) + for _, w := range targetWords { + x := 0 + for _, c := range w { + x |= 1 << (c - 'a') } - for _, c := range word { - t := mask ^ (1 << (c - 'a')) - if s[t] { + for _, c := range w { + if s[x^(1<<(c-'a'))] { ans++ break } } } - return ans + return +} +``` + +#### TypeScript + +```ts +function wordCount(startWords: string[], targetWords: string[]): number { + const s = new Set(); + for (const w of startWords) { + let x = 0; + for (const c of w) { + x ^= 1 << (c.charCodeAt(0) - 97); + } + s.add(x); + } + let ans = 0; + for (const w of targetWords) { + let x = 0; + for (const c of w) { + x ^= 1 << (c.charCodeAt(0) - 97); + } + for (const c of w) { + if (s.has(x ^ (1 << (c.charCodeAt(0) - 97)))) { + ++ans; + break; + } + } + } + return ans; } ``` diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README_EN.md b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README_EN.md index 620fa277596d0..ed5472a92d163 100644 --- a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README_EN.md +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README_EN.md @@ -86,7 +86,13 @@ tags: -### Solution 1 +### Solution 1: Hash Table + Bit Manipulation + +We notice that the given strings only contain lowercase letters, and each letter in a string appears at most once. Therefore, we can represent a string with a binary number of length $26$, where the $i$-th bit being $1$ indicates that the string contains the $i$-th lowercase letter, and $0$ indicates the absence of the $i$-th lowercase letter. + +We can convert each string in the array $\text{startWords}$ into a binary number and store these binary numbers in a set $\text{s}$. For each string in the array $\text{targetWords}$, we first convert it into a binary number, then enumerate each letter in this string, remove this letter from the binary number, and check if there exists a binary number in the set $\text{s}$ such that the XOR result of this binary number with the removed letter's binary number is in the set $\text{s}$. If such a binary number exists, then this string can be obtained by performing a transformation operation on some string in $\text{startWords}$, and we increment the answer by one. Then, we skip this string and continue processing the next string. + +The time complexity is $O(n \times |\Sigma|)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string array $\text{targetWords}$, and $|\Sigma|$ is the size of the character set in the string, which is $26$ in this problem. @@ -95,21 +101,12 @@ tags: ```python class Solution: def wordCount(self, startWords: List[str], targetWords: List[str]) -> int: - s = set() - for word in startWords: - mask = 0 - for c in word: - mask |= 1 << (ord(c) - ord('a')) - s.add(mask) - + s = {sum(1 << (ord(c) - 97) for c in w) for w in startWords} ans = 0 - for word in targetWords: - mask = 0 - for c in word: - mask |= 1 << (ord(c) - ord('a')) - for c in word: - t = mask ^ (1 << (ord(c) - ord('a'))) - if t in s: + for w in targetWords: + x = sum(1 << (ord(c) - 97) for c in w) + for c in w: + if x ^ (1 << (ord(c) - 97)) in s: ans += 1 break return ans @@ -119,25 +116,23 @@ class Solution: ```java class Solution { - public int wordCount(String[] startWords, String[] targetWords) { Set s = new HashSet<>(); - for (String word : startWords) { - int mask = 0; - for (char c : word.toCharArray()) { - mask |= (1 << (c - 'a')); + for (var w : startWords) { + int x = 0; + for (var c : w.toCharArray()) { + x |= 1 << (c - 'a'); } - s.add(mask); + s.add(x); } int ans = 0; - for (String word : targetWords) { - int mask = 0; - for (char c : word.toCharArray()) { - mask |= (1 << (c - 'a')); + for (var w : targetWords) { + int x = 0; + for (var c : w.toCharArray()) { + x |= 1 << (c - 'a'); } - for (char c : word.toCharArray()) { - int t = mask ^ (1 << (c - 'a')); - if (s.contains(t)) { + for (var c : w.toCharArray()) { + if (s.contains(x ^ (1 << (c - 'a')))) { ++ans; break; } @@ -155,20 +150,21 @@ class Solution { public: int wordCount(vector& startWords, vector& targetWords) { unordered_set s; - for (auto& word : startWords) { - int mask = 0; - for (char c : word) - mask |= (1 << (c - 'a')); - s.insert(mask); + for (auto& w : startWords) { + int x = 0; + for (char c : w) { + x |= 1 << (c - 'a'); + } + s.insert(x); } int ans = 0; - for (auto& word : targetWords) { - int mask = 0; - for (char c : word) - mask |= (1 << (c - 'a')); - for (char c : word) { - int t = mask ^ (1 << (c - 'a')); - if (s.count(t)) { + for (auto& w : targetWords) { + int x = 0; + for (char c : w) { + x |= 1 << (c - 'a'); + } + for (char c : w) { + if (s.contains(x ^ (1 << (c - 'a')))) { ++ans; break; } @@ -182,30 +178,57 @@ public: #### Go ```go -func wordCount(startWords []string, targetWords []string) int { - s := make(map[int]bool) - for _, word := range startWords { - mask := 0 - for _, c := range word { - mask |= (1 << (c - 'a')) +func wordCount(startWords []string, targetWords []string) (ans int) { + s := map[int]bool{} + for _, w := range startWords { + x := 0 + for _, c := range w { + x |= 1 << (c - 'a') } - s[mask] = true + s[x] = true } - ans := 0 - for _, word := range targetWords { - mask := 0 - for _, c := range word { - mask |= (1 << (c - 'a')) + for _, w := range targetWords { + x := 0 + for _, c := range w { + x |= 1 << (c - 'a') } - for _, c := range word { - t := mask ^ (1 << (c - 'a')) - if s[t] { + for _, c := range w { + if s[x^(1<<(c-'a'))] { ans++ break } } } - return ans + return +} +``` + +#### TypeScript + +```ts +function wordCount(startWords: string[], targetWords: string[]): number { + const s = new Set(); + for (const w of startWords) { + let x = 0; + for (const c of w) { + x ^= 1 << (c.charCodeAt(0) - 97); + } + s.add(x); + } + let ans = 0; + for (const w of targetWords) { + let x = 0; + for (const c of w) { + x ^= 1 << (c.charCodeAt(0) - 97); + } + for (const c of w) { + if (s.has(x ^ (1 << (c.charCodeAt(0) - 97)))) { + ++ans; + break; + } + } + } + return ans; } ``` diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.cpp b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.cpp index 309f39c0308b1..4cef56a66e5ae 100644 --- a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.cpp +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.cpp @@ -2,20 +2,21 @@ class Solution { public: int wordCount(vector& startWords, vector& targetWords) { unordered_set s; - for (auto& word : startWords) { - int mask = 0; - for (char c : word) - mask |= (1 << (c - 'a')); - s.insert(mask); + for (auto& w : startWords) { + int x = 0; + for (char c : w) { + x |= 1 << (c - 'a'); + } + s.insert(x); } int ans = 0; - for (auto& word : targetWords) { - int mask = 0; - for (char c : word) - mask |= (1 << (c - 'a')); - for (char c : word) { - int t = mask ^ (1 << (c - 'a')); - if (s.count(t)) { + for (auto& w : targetWords) { + int x = 0; + for (char c : w) { + x |= 1 << (c - 'a'); + } + for (char c : w) { + if (s.contains(x ^ (1 << (c - 'a')))) { ++ans; break; } diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.go b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.go index 44500e0dd541d..6a79b10386356 100644 --- a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.go +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.go @@ -1,25 +1,23 @@ -func wordCount(startWords []string, targetWords []string) int { - s := make(map[int]bool) - for _, word := range startWords { - mask := 0 - for _, c := range word { - mask |= (1 << (c - 'a')) +func wordCount(startWords []string, targetWords []string) (ans int) { + s := map[int]bool{} + for _, w := range startWords { + x := 0 + for _, c := range w { + x |= 1 << (c - 'a') } - s[mask] = true + s[x] = true } - ans := 0 - for _, word := range targetWords { - mask := 0 - for _, c := range word { - mask |= (1 << (c - 'a')) + for _, w := range targetWords { + x := 0 + for _, c := range w { + x |= 1 << (c - 'a') } - for _, c := range word { - t := mask ^ (1 << (c - 'a')) - if s[t] { + for _, c := range w { + if s[x^(1<<(c-'a'))] { ans++ break } } } - return ans + return } \ No newline at end of file diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.java b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.java index 3936e4274895c..46b3e987c7823 100644 --- a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.java +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.java @@ -1,23 +1,21 @@ class Solution { - public int wordCount(String[] startWords, String[] targetWords) { Set s = new HashSet<>(); - for (String word : startWords) { - int mask = 0; - for (char c : word.toCharArray()) { - mask |= (1 << (c - 'a')); + for (var w : startWords) { + int x = 0; + for (var c : w.toCharArray()) { + x |= 1 << (c - 'a'); } - s.add(mask); + s.add(x); } int ans = 0; - for (String word : targetWords) { - int mask = 0; - for (char c : word.toCharArray()) { - mask |= (1 << (c - 'a')); + for (var w : targetWords) { + int x = 0; + for (var c : w.toCharArray()) { + x |= 1 << (c - 'a'); } - for (char c : word.toCharArray()) { - int t = mask ^ (1 << (c - 'a')); - if (s.contains(t)) { + for (var c : w.toCharArray()) { + if (s.contains(x ^ (1 << (c - 'a')))) { ++ans; break; } diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.py b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.py index 68f02111f7242..88053e5b0dd9a 100644 --- a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.py +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.py @@ -1,20 +1,11 @@ class Solution: def wordCount(self, startWords: List[str], targetWords: List[str]) -> int: - s = set() - for word in startWords: - mask = 0 - for c in word: - mask |= 1 << (ord(c) - ord('a')) - s.add(mask) - + s = {sum(1 << (ord(c) - 97) for c in w) for w in startWords} ans = 0 - for word in targetWords: - mask = 0 - for c in word: - mask |= 1 << (ord(c) - ord('a')) - for c in word: - t = mask ^ (1 << (ord(c) - ord('a'))) - if t in s: + for w in targetWords: + x = sum(1 << (ord(c) - 97) for c in w) + for c in w: + if x ^ (1 << (ord(c) - 97)) in s: ans += 1 break return ans diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.ts b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.ts new file mode 100644 index 0000000000000..8492705ceec2b --- /dev/null +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/Solution.ts @@ -0,0 +1,24 @@ +function wordCount(startWords: string[], targetWords: string[]): number { + const s = new Set(); + for (const w of startWords) { + let x = 0; + for (const c of w) { + x ^= 1 << (c.charCodeAt(0) - 97); + } + s.add(x); + } + let ans = 0; + for (const w of targetWords) { + let x = 0; + for (const c of w) { + x ^= 1 << (c.charCodeAt(0) - 97); + } + for (const c of w) { + if (s.has(x ^ (1 << (c.charCodeAt(0) - 97)))) { + ++ans; + break; + } + } + } + return ans; +} diff --git a/solution/2100-2199/2136.Earliest Possible Day of Full Bloom/README_EN.md b/solution/2100-2199/2136.Earliest Possible Day of Full Bloom/README_EN.md index 8f7a09700fc97..a4179fe294060 100644 --- a/solution/2100-2199/2136.Earliest Possible Day of Full Bloom/README_EN.md +++ b/solution/2100-2199/2136.Earliest Possible Day of Full Bloom/README_EN.md @@ -83,7 +83,11 @@ Thus, on day 2, all the seeds are blooming. -### Solution 1 +### Solution 1: Greedy + Sorting + +According to the problem description, we know that only one seed can be planted per day. Therefore, regardless of the planting order, the sum of the planting times for all seeds is always equal to $\sum_{i=0}^{n-1} plantTime[i]$. To make all seeds bloom as soon as possible, we should prioritize planting the seeds with the longest growth time. Hence, we can sort all seeds by their growth time in descending order and then plant them in sequence. + +The time complexity is $O(n \log n)$, and the space complexity is $O(n)$, where $n$ is the number of seeds. diff --git a/solution/2100-2199/2137.Pour Water Between Buckets to Make Water Levels Equal/README_EN.md b/solution/2100-2199/2137.Pour Water Between Buckets to Make Water Levels Equal/README_EN.md index 2b042258e9e8d..efa8c719af0e2 100644 --- a/solution/2100-2199/2137.Pour Water Between Buckets to Make Water Levels Equal/README_EN.md +++ b/solution/2100-2199/2137.Pour Water Between Buckets to Make Water Levels Equal/README_EN.md @@ -70,7 +70,15 @@ All buckets have 3.5 gallons of water in them so return 3.5. -### Solution 1 +### Solution 1: Binary Search for Floating-Point Numbers + +We notice that if a water volume $x$ meets the condition, then all water volumes less than $x$ also meet the condition. Therefore, we can use binary search to find the maximum water volume that satisfies the condition. + +We define the left boundary of the binary search as $l=0$ and the right boundary as $r=\max(buckets)$. During each binary search iteration, we take the midpoint $mid$ of $l$ and $r$, and check if $mid$ meets the condition. If it does, we update $l$ to $mid$; otherwise, we update $r$ to $mid$. After the binary search concludes, the maximum water volume that satisfies the condition is $l$. + +The key to the problem is to determine if a water volume $v$ meets the condition. We can iterate through all buckets, and for each bucket, if its water volume is greater than $v$, then we need to pour out $x-v$ water volume; if its water volume is less than $v$, then we need to pour in $(v-x)\times\frac{100}{100-\textit{loss}}$ water volume. If the total volume poured out is greater than or equal to the volume poured in, then $v$ meets the condition. + +The time complexity is $O(n \times \log M)$, where $n$ and $M$ are the length and the maximum value of the array $buckets$, respectively. The time complexity of binary search is $O(\log M)$, and each binary search iteration requires traversing the array $buckets$, with a time complexity of $O(n)$. The space complexity is $O(1)$.