Given a string array words
, return an array of all characters that show up in all strings within the words
(including duplicates). You may return the answer in any order.
Example 1:
Input: words = ["bella","label","roller"] Output: ["e","l","l"]
Example 2:
Input: words = ["cool","lock","cook"] Output: ["c","o"]
Constraints:
1 <= words.length <= 100
1 <= words[i].length <= 100
words[i]
consists of lowercase English letters.This problem asks to find all characters that appear in all input strings, including duplicates. The most efficient approach uses a frequency counting method.
Approach:
Initialization: We start by creating a frequency counter (e.g., an array or a hash map). The counter will store the minimum number of times each character appears across all input strings. We initialize this counter with a sufficiently large value (e.g., 20000) for each character to ensure that the minimum count will always be less.
Iterating Through Strings: We iterate through each string in the input array (words
). For each string:
t
) to count character occurrences in the current string.cnt
) by taking the minimum count for each character between the current string's count and the existing minimum count. This ensures we're only keeping characters that appear in all strings.Constructing the Result: Finally, we iterate through the main frequency counter. For each character with a count greater than 0, we add that character to the result array as many times as its count indicates (to account for duplicates).
Time Complexity: O(N*M), where N is the number of strings in words
, and M is the maximum length of a string. This is because we iterate through each string once (O(N)) and process each character within each string (O(M) for the longest string).
Space Complexity: O(1). We use a fixed-size array (26 elements for the 26 lowercase English letters) to store character frequencies, making the space complexity constant regardless of the input size.
Code Examples (with explanations):
Python:
from collections import Counter
class Solution:
def commonChars(self, words: List[str]) -> List[str]:
cnt = Counter(words[0]) #Initialize counter with first string's frequencies
for word in words[1:]: #Iterate from the second string
t = Counter(word)
for char in cnt: #Update minimum count for each character
cnt[char] = min(cnt[char], t[char])
result = []
for char, count in cnt.items(): #Build result from minimum counts
result.extend([char] * count) #Add character 'count' times
return result
Java:
import java.util.*;
class Solution {
public List<String> commonChars(String[] words) {
int[] cnt = new int[26]; // Frequency counter (initialized to large values)
Arrays.fill(cnt, 20000);
for (String word : words) {
int[] t = new int[26]; //Temp counter for each word
for (char c : word.toCharArray()) {
t[c - 'a']++;
}
for (int i = 0; i < 26; ++i) {
cnt[i] = Math.min(cnt[i], t[i]); // Update minimum counts
}
}
List<String> ans = new ArrayList<>();
for (int i = 0; i < 26; ++i) {
for (int j = 0; j < cnt[i]; ++j) {
ans.add(String.valueOf((char) ('a' + i)));
}
}
return ans;
}
}
The other languages (C++, Go, TypeScript) follow a very similar structure, adapting the syntax to their respective language features. The core logic of frequency counting and minimum count updates remains the same.