「本文已参与低调务实优秀中国好青年前端社群的写作活动」
一、题目描述
给你两个下标从 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 。
有如下限制条件:不管顺序,但拼凑的字符只能使用一次。
解题思路:
- 使用
map数据结构,命名为mapt,存储target中每个元素出现的次数。 - 使用
map数据结构,命名为maps,存储s中字符为target其中之一的元素出现的次数。 - 定义
res,表示s中可以拼凑出target的数量。 - 遍历
mapt,获取遍历到元素的key和value,判断maps中是否含有当前元素:如果没有,直接return 0;如果有,获取maps中该元素的数量,除以mapt中该元素的数量并向下取整,赋值给num。根据短板效应,能拼凑出target的数量取决于最小的那个num,因此要实时更新res。
三、AC 代码
/**
* @param {string} s
* @param {string} target
* @return {number}
*/
var rearrangeCharacters = function(s, target) {
let res = Infinity;
let maps = new Map();
let mapt = new Map();
for (let word of s) {
if (target.includes(word)) {
let num = maps.has(word) ? maps.get(word) : 0;
maps.set(word, ++num);
}
}
for (let word of target) {
let num = mapt.has(word) ? mapt.get(word) : 0;
mapt.set(word, ++num);
}
for (let [key, value] of mapt) {
if (!maps.has(key)) return 0;
res = Math.min(res, Math.floor(maps.get(key) / value));
}
return res;
};