Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given two 0-indexed arrays of strings startWords and targetWords. Each string consists of lowercase English letters only.
For each string in targetWords, check if it is possible to choose a string from startWords and perform a conversion operation on it to be equal to that from targetWords.
The conversion operation is described in the following two steps:
"abc", the letters 'd', 'e', or 'y' can be added to it, but not 'a'. If 'd' is added, the resulting string will be "abcd"."abcd" can be rearranged to "acbd", "bacd", "cbda", and so on. Note that it can also be rearranged to "abcd" itself.Return the number of strings in targetWords that can be obtained by performing the operations on any string of startWords.
Note that you will only be verifying if the string in targetWords can be obtained from a string in startWords by performing the operations. The strings in startWords do not actually change during this process.
Example 1:
Input: startWords = ["ant","act","tack"], targetWords = ["tack","act","acti"] Output: 2 Explanation: - In order to form targetWords[0] = "tack", we use startWords[1] = "act", append 'k' to it, and rearrange "actk" to "tack". - There is no string in startWords that can be used to obtain targetWords[1] = "act". Note that "act" does exist in startWords, but we must append one letter to the string before rearranging it. - In order to form targetWords[2] = "acti", we use startWords[1] = "act", append 'i' to it, and rearrange "acti" to "acti" itself.
Example 2:
Input: startWords = ["ab","a"], targetWords = ["abc","abcd"] Output: 1 Explanation: - In order to form targetWords[0] = "abc", we use startWords[0] = "ab", add 'c' to it, and rearrange it to "abc". - There is no string in startWords that can be used to obtain targetWords[1] = "abcd".
Constraints:
1 <= startWords.length, targetWords.length <= 5 * 1041 <= startWords[i].length, targetWords[j].length <= 26startWords and targetWords consists of lowercase English letters only.startWords or targetWords.Problem summary: You are given two 0-indexed arrays of strings startWords and targetWords. Each string consists of lowercase English letters only. For each string in targetWords, check if it is possible to choose a string from startWords and perform a conversion operation on it to be equal to that from targetWords. The conversion operation is described in the following two steps: Append any lowercase letter that is not present in the string to its end. For example, if the string is "abc", the letters 'd', 'e', or 'y' can be added to it, but not 'a'. If 'd' is added, the resulting string will be "abcd". Rearrange the letters of the new string in any arbitrary order. For example, "abcd" can be rearranged to "acbd", "bacd", "cbda", and so on. Note that it can also be rearranged to "abcd" itself. Return the number of strings in targetWords that can be obtained by performing the operations on any string of
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Hash Map · Bit Manipulation
["ant","act","tack"] ["tack","act","acti"]
["ab","a"] ["abc","abcd"]
strings-differ-by-one-character)count-substrings-that-differ-by-one-character)maximum-score-from-removing-substrings)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2135: Count Words Obtained After Adding a Letter
class Solution {
public int wordCount(String[] startWords, String[] targetWords) {
Set<Integer> s = new HashSet<>();
for (var w : startWords) {
int x = 0;
for (var c : w.toCharArray()) {
x |= 1 << (c - 'a');
}
s.add(x);
}
int ans = 0;
for (var w : targetWords) {
int x = 0;
for (var c : w.toCharArray()) {
x |= 1 << (c - 'a');
}
for (var c : w.toCharArray()) {
if (s.contains(x ^ (1 << (c - 'a')))) {
++ans;
break;
}
}
}
return ans;
}
}
// Accepted solution for LeetCode #2135: Count Words Obtained After Adding a Letter
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[x] = true
}
for _, w := range targetWords {
x := 0
for _, c := range w {
x |= 1 << (c - 'a')
}
for _, c := range w {
if s[x^(1<<(c-'a'))] {
ans++
break
}
}
}
return
}
# Accepted solution for LeetCode #2135: Count Words Obtained After Adding a Letter
class Solution:
def wordCount(self, startWords: List[str], targetWords: List[str]) -> int:
s = {sum(1 << (ord(c) - 97) for c in w) for w in startWords}
ans = 0
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
// Accepted solution for LeetCode #2135: Count Words Obtained After Adding a Letter
/**
* [2135] Count Words Obtained After Adding a Letter
*
* You are given two 0-indexed arrays of strings startWords and targetWords. Each string consists of lowercase English letters only.
* For each string in targetWords, check if it is possible to choose a string from startWords and perform a conversion operation on it to be equal to that from targetWords.
* The conversion operation is described in the following two steps:
* <ol>
* Append any lowercase letter that is not present in the string to its end.
*
* For example, if the string is "abc", the letters 'd', 'e', or 'y' can be added to it, but not 'a'. If 'd' is added, the resulting string will be "abcd".
*
*
* Rearrange the letters of the new string in any arbitrary order.
*
* For example, "abcd" can be rearranged to "acbd", "bacd", "cbda", and so on. Note that it can also be rearranged to "abcd" itself.
*
*
* </ol>
* Return the number of strings in targetWords that can be obtained by performing the operations on any string of startWords.
* Note that you will only be verifying if the string in targetWords can be obtained from a string in startWords by performing the operations. The strings in startWords do not actually change during this process.
*
* Example 1:
*
* Input: startWords = ["ant","act","tack"], targetWords = ["tack","act","acti"]
* Output: 2
* Explanation:
* - In order to form targetWords[0] = "tack", we use startWords[1] = "act", append 'k' to it, and rearrange "actk" to "tack".
* - There is no string in startWords that can be used to obtain targetWords[1] = "act".
* Note that "act" does exist in startWords, but we must append one letter to the string before rearranging it.
* - In order to form targetWords[2] = "acti", we use startWords[1] = "act", append 'i' to it, and rearrange "acti" to "acti" itself.
*
* Example 2:
*
* Input: startWords = ["ab","a"], targetWords = ["abc","abcd"]
* Output: 1
* Explanation:
* - In order to form targetWords[0] = "abc", we use startWords[0] = "ab", add 'c' to it, and rearrange it to "abc".
* - There is no string in startWords that can be used to obtain targetWords[1] = "abcd".
*
*
* Constraints:
*
* 1 <= startWords.length, targetWords.length <= 5 * 10^4
* 1 <= startWords[i].length, targetWords[j].length <= 26
* Each string of startWords and targetWords consists of lowercase English letters only.
* No letter occurs more than once in any string of startWords or targetWords.
*
*/
pub struct Solution {}
// problem: https://leetcode.com/problems/count-words-obtained-after-adding-a-letter/
// discuss: https://leetcode.com/problems/count-words-obtained-after-adding-a-letter/discuss/?currentPage=1&orderBy=most_votes&query=
// submission codes start here
impl Solution {
pub fn word_count(start_words: Vec<String>, target_words: Vec<String>) -> i32 {
0
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn test_2135_example_1() {
let start_words = vec_string!["ant", "act", "tack"];
let target_words = vec_string!["tack", "act", "acti"];
let result = 2;
assert_eq!(Solution::word_count(start_words, target_words), result);
}
#[test]
#[ignore]
fn test_2135_example_2() {
let start_words = vec_string!["ab", "a"];
let target_words = vec_string!["abc", "abcd"];
let result = 1;
assert_eq!(Solution::word_count(start_words, target_words), result);
}
}
// Accepted solution for LeetCode #2135: Count Words Obtained After Adding a Letter
function wordCount(startWords: string[], targetWords: string[]): number {
const s = new Set<number>();
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;
}
Use this to step through a reusable interview workflow for this problem.
Sort the array in O(n log n), then scan for the missing or unique element by comparing adjacent pairs. Sorting requires O(n) auxiliary space (or O(1) with in-place sort but O(n log n) time remains). The sort step dominates.
Bitwise operations (AND, OR, XOR, shifts) are O(1) per operation on fixed-width integers. A single pass through the input with bit operations gives O(n) time. The key insight: XOR of a number with itself is 0, which eliminates duplicates without extra space.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.