重新分配字符使所有字符串都相等

88 阅读2分钟

🎈 算法并不一定都是很难的题目,也有很多只是一些代码技巧,多进行一些算法题目的练习,可以帮助我们开阔解题思路,提升我们的逻辑思维能力,也可以将一些算法思维结合到业务代码的编写思考中。简而言之,平时进行的算法习题练习带给我们的好处一定是不少的,所以让我们一起来养成算法练习的习惯。今天练习的题目是一道比较简单的题目 ->重新分配字符使所有字符串都相等

问题描述

给你一个字符串数组  words(下标  从 0 开始  计数)。

在一步操作中,需先选出两个  不同  下标  i  和  j,其中  words[i]  是一个非空字符串,接着将  words[i]  中的  任一  字符移动到  words[j]  中的  任一  位置上。

如果执行任意步操作可以使  words  中的每个字符串都相等,返回  true **;否则,返回 **false 。

示例 1:

输入: words = ["abc","aabc","bc"]
输出: true
解释: 将 words[1] 中的第一个 'a' 移动到 words[2] 的最前面。
使 words[1] = "abc" 且 words[2] = "abc" 。
所有字符串都等于 "abc" ,所以返回 true

示例 2:

输入: words = ["ab","a"]
输出: false
解释: 执行操作无法使所有字符串都相等。

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 100
  • words[i]  由小写英文字母组成

解题思路

首先我们需要先理解一下题目的意思,题目会给我们一个字符串数组  words,我们可以执行任意次数的操作,每次操作可以将  words[i]  中的  任一  字符移动到  words[j]  中的  任一  位置上,其中 i !+ j,我们需要判断执行任意步操作可不可以使  words  中的每个字符串都相等,可以的话返回  true **;否则,返回 **false 。

咋一看题目是不是会觉得无从入手,不知道要怎么去模拟题目描述的这系列操作,这个时候我们就应该换个思路来想想了,题目说了我们可以执行任意次数的操作,也就是说我们可以做到将所有字符进行重组,而重组能组成的字符串数组取决于原有字符串数组中每种字符的数量,我们只需要保持重组的字符串数量和原有的字符串数量一致即可,那么我们可以这样做:

  • 1、统计字符串中每种字符的数量

直接遍历给出的字符串数组,再遍历字符串获取字符串中的每一个字符,使用一个哈希表来统计每一个字母出现的个数

let map = {};
words.forEach((word) => {
  for (const w of word) {
    map[w] = (map[w] || 0) + 1;
  }
});
  • 2、判断能否重组成words.length个相同的字符串

如果每个字母出现的个数都是words.length的倍数,那么我们便可以将其平均分到每一个字符串中,这样每一个字符串中的相同字母出现的个数就是一样的,而且其位置我们也可以任意调整,所以也就说明我们可以重组成words.length个相同的字符串,如果其中有一个字母出现的个数不是words.length的倍数则说明不能重组成words.length个相同的字符串。

for (const key in map) {
  if (map[key] % words.length !== 0) return false;
}
return true;

AC 代码

完整AC代码如下:

/**
 * @param {string[]} words
 * @return {boolean}
 */
var makeEqual = function (words) {
  let map = {};
  words.forEach((word) => {
    for (const w of word) {
      map[w] = (map[w] || 0) + 1;
    }
  });
  for (const key in map) {
    if (map[key] % words.length !== 0) return false;
  }
  return true;
};

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,在此谢谢大家的支持,我们下文再见 🙌。