1897. Redistribute Characters to Make All Strings Equal
Description
You are given an array of strings words
(0-indexed).
In one operation, pick two distinct indices i
and j
, where words[i]
is a non-empty string, and move any character from words[i]
to any position in words[j]
.
Return true
if you can make every string in words
equal using any number of operations, and false
otherwise.
Example 1:
Input: words = ["abc","aabc","bc"] Output: true Explanation: Move the first 'a' inwords[1] to the front of words[2], to make
words[1]
= "abc" and words[2] = "abc". All the strings are now equal to "abc", so returntrue
.
Example 2:
Input: words = ["ab","a"] Output: false Explanation: It is impossible to make all the strings equal using the operation.
Constraints:
1 <= words.length <= 100
1 <= words[i].length <= 100
words[i]
consists of lowercase English letters.
Solutions
Solution 1: Counting
According to the problem description, as long as the occurrence count of each character can be divided by the length of the string array, it is possible to redistribute the characters to make all strings equal.
Therefore, we use a hash table or an integer array of length $26$ $\textit{cnt}$ to count the occurrences of each character. Finally, we check if the occurrence count of each character can be divided by the length of the string array.
The time complexity is $O(L)$, and the space complexity is $O(|\Sigma|)$. Here, $L$ is the total length of all strings in the array $\textit{words}$, and $\Sigma$ is the character set, which is the set of lowercase letters, so $|\Sigma|=26$.
Python3
class Solution:
def makeEqual(self, words: List[str]) -> bool:
cnt = Counter()
for w in words:
for c in w:
cnt[c] += 1
n = len(words)
return all(v % n == 0 for v in cnt.values())
Java
class Solution {
public boolean makeEqual(String[] words) {
int[] cnt = new int[26];
for (var w : words) {
for (char c : w.toCharArray()) {
++cnt[c - 'a'];
}
}
int n = words.length;
for (int v : cnt) {
if (v % n != 0) {
return false;
}
}
return true;
}
}
C++
class Solution {
public:
bool makeEqual(vector<string>& words) {
int cnt[26]{};
for (const auto& w : words) {
for (const auto& c : w) {
++cnt[c - 'a'];
}
}
int n = words.size();
for (int i = 0; i < 26; ++i) {
if (cnt[i] % n != 0) {
return false;
}
}
return true;
}
};
Go
func makeEqual(words []string) bool {
cnt := [26]int{}
for _, w := range words {
for _, c := range w {
cnt[c-'a']++
}
}
n := len(words)
for _, v := range cnt {
if v%n != 0 {
return false
}
}
return true
}
TypeScript
function makeEqual(words: string[]): boolean {
const cnt: Record<string, number> = {};
for (const w of words) {
for (const c of w) {
cnt[c] = (cnt[c] || 0) + 1;
}
}
const n = words.length;
return Object.values(cnt).every(v => v % n === 0);
}
Rust
impl Solution {
pub fn make_equal(words: Vec<String>) -> bool {
let mut cnt = std::collections::HashMap::new();
for word in words.iter() {
for c in word.chars() {
*cnt.entry(c).or_insert(0) += 1;
}
}
let n = words.len();
cnt.values().all(|&v| v % n == 0)
}
}