持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
现在前端很多岗位面试需要有一定的算法基础,或者说经常刷算法的会优先考虑。
因此每天刷刷LeetCode非常有必要
在这之前我也刷过一些算法题,也希望以后也坚持刷,跟某掘友一样,我也想刷穿 LeetCode
一、题目描述
我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。
您想要拼写出给定的字符串 target ,方法是从收集的贴纸中切割单个字母并重新排列它们。如果你愿意,你可以多次使用每个贴纸,每个贴纸的数量是无限的。
返回你需要拼出 target 的最小贴纸数量。如果任务不可能,则返回 -1 。
注意:在所有的测试用例中,所有的单词都是从 1000 个最常见的美国英语单词中随机选择的,并且 target 被选择为两个随机单词的连接。
示例 1:
输入: stickers = ["with","example","science"], target = "thehat" 输出:3 解释: 我们可以使用 2 个 "with" 贴纸,和 1 个 "example" 贴纸。 把贴纸上的字母剪下来并重新排列后,就可以形成目标 “thehat“ 了。 此外,这是形成目标字符串所需的最小贴纸数量。
二、思路分析
- 把stickers中的每一项(字符串)放入一个长度为26的数组里,数组的下标代表当前字符的charCode相对'a'的charCode的偏移量
- 把target(字符串)放入一个长度为26的数组里,数组的下标代表当前字符的charCode相对'a'的charCode的偏移量
- stickers中以每一项作为第一个,所有分支挨个试一遍
- 剪枝优化,当前的sticker包含target中的第一个字符
三、代码实现
/**
* @param {string[]} stickers
* @param {string} target
* @return {number}
*/
const ACharCode = 97;
var minStickers = function(stickers, target) {
const N = stickers.length;
let counts = Array(N).fill().map(() => Array(26).fill(0));
let charCodeIndex;
// 把stickers中的每一项(字符串)放入一个长度为26的数组里,数组的下标代表当前字符的charCode相对'a'的charCode的偏移量
for(let i = 0; i < N; i++) {
for (let j = 0; j < stickers[i].length; j++) {
charCodeIndex = stickers[i][j].charCodeAt(0) - ACharCode;
counts[i][charCodeIndex]++;
}
}
let dp = new Map();
dp.set("", 0);
let ans = process(counts, target, dp);
return ans === Number.MAX_SAFE_INTEGER ? -1 : ans;
};
function process(stickers, t, dp) {
if (dp.has(t)) {
return dp.get(t);
}
// 把target(字符串)放入一个长度为26的数组里,数组的下标代表当前字符的charCode相对'a'的charCode的偏移量
let tcounts = Array(26).fill(0);
for (let i = 0; i < t.length; i++) {
tcounts[t[i].charCodeAt(0) - ACharCode]++;
}
const N = stickers.length;
let min = Number.MAX_SAFE_INTEGER;
// stickers中以每一项作为第一个,所有分支挨个试一遍
for (let i = 0; i < N; i++) {
let sticker = stickers[i];
// 剪枝优化,当前的sticker包含target中的第一个字符
if (sticker[t.charCodeAt(0) - ACharCode] > 0) {
let builder = [];
for (let j = 0; j < 26; j++) {
if (tcounts[j] > 0) {
let nums = tcounts[j] - sticker[j];
for (let k = 0; k < nums; k++) {
builder.push(j + ACharCode);
}
}
}
const rest = String.fromCharCode(...builder);
min = Math.min(min, process(stickers, rest, dp));
}
}
let ans = min + ((min === Number.MAX_SAFE_INTEGER) ? 0 : 1);
dp.set(t, ans);
return ans;
}
四、总结
以上就是本道题的所有内容了,本系列会持续更,欢迎点赞、关注、收藏,另外如有其他的问题,欢迎下方留言给我,我会第一时间回复你,感谢~