{x}
blog image

Find Common Characters

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.

Solution Explanation: Finding Common Characters

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:

  1. 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.

  2. Iterating Through Strings: We iterate through each string in the input array (words). For each string:

    • We create a temporary frequency counter (t) to count character occurrences in the current string.
    • We update the main frequency counter (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.
  3. 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.