持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
说在前面
🎈每天进行一道算法题目练习,今天的题目是“重排字符形成目标字符串”。
问题描述
给你两个下标从 0 开始的字符串 s 和 target 。你可以从 s 取出一些字符并将其重排,得到若干新的字符串。
从 s 中取出字符并重新排列,返回可以形成 target 的 最大 副本数。
示例 1:
输入: s = "ilovecodingonleetcode", target = "code"
输出: 2
解释:
对于 "code" 的第 1 个副本,选取下标为 4 、5 、6 和 7 的字符。
对于 "code" 的第 2 个副本,选取下标为 17 、18 、19 和 20 的字符。
形成的字符串分别是 "ecod" 和 "code" ,都可以重排为 "code" 。
可以形成最多 2 个 "code" 的副本,所以返回 2 。
示例 2:
输入: s = "abcba", target = "abc"
输出: 1
解释:
选取下标为 0 、1 和 2 的字符,可以形成 "abc" 的 1 个副本。
可以形成最多 1 个 "abc" 的副本,所以返回 1 。
注意,尽管下标 3 和 4 分别有额外的 'a' 和 'b' ,但不能重用下标 2 处的 'c' ,所以无法形成 "abc" 的第 2 个副本。
示例 3:
输入: s = "abbaccaddaeea", target = "aaaaa"
输出: 1
解释:
选取下标为 0 、3 、6 、9 和 12 的字符,可以形成 "aaaaa" 的 1 个副本。
可以形成最多 1 个 "aaaaa" 的副本,所以返回 1 。
提示:
1 <= s.length <= 1001 <= target.length <= 10s和target由小写英文字母组成
思路分析
由题目描述我们可以知道,我们需要计算使用给出的字符串s中的字母,重排可以构建成几个target字符串。由示例我们可以知道,s字符串中的字符并不能重复使用,也就是说我们只需要知道目标字符串target中每个字母在s中出现的次数,便可以使用木桶原理来得出可以组成的最多组数。这里有一点需要注意的地方,就是target字符串中有可能会有重复出现的字符,所以我们不能简单的比较一个字符出现的次数,我们还需要将一个字符在s字符串中出现的次数除于其在target字符串中出现的次数,得到的就是这个字符可以填补上多少个target字符串中的字符,具体步骤如下:
- 1、计算s字符串中每个字符出现的次数
for (let i = 0; i < s.length; i++) {
m[s[i]] = (m[s[i]] || 0) + 1;
}
- 2、计算target字符串中每个字符出现的次数
for (let i = 0; i < target.length; i++) {
n[target[i]] = (n[target[i]] || 0) + 1;
}
- 3、利用木桶原理求出可以组成的最大数量
for (let i = 0; i < target.length; i++) {
res = Math.min(res, Math.floor((m[target[i]] || 0) / n[target[i]]));
}
AC代码
/**
* @param {string} s
* @param {string} target
* @return {number}
*/
var rearrangeCharacters = function (s, target) {
let m = {},
n = {};
for (let i = 0; i < s.length; i++) {
m[s[i]] = (m[s[i]] || 0) + 1;
}
for (let i = 0; i < target.length; i++) {
n[target[i]] = (n[target[i]] || 0) + 1;
}
let res = Infinity;
for (let i = 0; i < target.length; i++) {
res = Math.min(res, Math.floor((m[target[i]] || 0) / n[target[i]]));
}
return res == Infinity ? 0 : res;
};
说在后面
🎉这里是JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,平时也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。