[Leetcode]691.Stickers to Spell Word
链接:LeetCode691
给出了 N 种不同类型的贴纸。每个贴纸上都有一个小写的英文单词。
你希望从自己的贴纸集合中裁剪单个字母并重新排列它们,从而拼写出给定的目标字符串 target。如果你愿意的话,你可以不止一次地使用每一张贴纸,而且每一张贴纸的数量都是无限的。拼出目标 target 所需的最小贴纸数量是多少?如果任务不可能,则返回 -1。
示例 1:
输入:
["with", "example", "science"], "thehat"
输出:
3
解释:
我们可以使用 2 个 "with" 贴纸,和 1 个 "example" 贴纸。
把贴纸上的字母剪下来并重新排列后,就可以形成目标 “thehat“ 了。
此外,这是形成目标字符串所需的最小贴纸数量。
相关标签:备忘录+回溯
这道题也可以看成是背包问题的变形题,在背包问题中我们要求总价值最大,而这里我们要求每个字符被用完。比较简单的做法是利用回溯方法,通过备忘录记住每个字符串的最小贴纸数量,防止出现重复遍历。
需要注意的是,为了判断目标字符串用掉一个贴纸后的情况,我们可以将字符串转化为26位的数组(因为是a-z的字符,且都为小写字母,这是一种常用节省内存的做法),对数组进行“按位减”。
另外,可以利用当该贴纸没有字符串出现的第一个字符即进行抛弃等trick,进行剪枝。
其代码如下:
python:
class Solution:
def minStickers(self, stickers: List[str], target: str) -> int:
n = len(stickers)
dic = {'':0}
count = [self.getCounter(sticker) for sticker in stickers]
res = self.dfs(count,target,dic)
return res if res!=float('inf') else -1
def dfs(self,count,target,dic):
if target in dic:
return dic[target]
tar = self.getCounter(target)
dic[target] = float('inf')
for i in range(len(count)):
if count[i][ord(target[0])-ord('a')]==0:continue
rest = ''
for j in range(26):
if tar[j] - count[i][j] > 0:
rest += chr(ord('a')+j) * (tar[j] - count[i][j])
dic[target] = min(dic[target],1+self.dfs(count,rest,dic))
return dic[target]
def getCounter(self,s):
res = [0 for _ in range(26)]
for ch in s:
res[ord(ch)-ord('a')]+=1
return res
C++:
class Solution {
public:
int minStickers(vector<string>& stickers, string target) {
int n = stickers.size();
vector<vector<int>> count(n,vector<int>(26,0));
for(int i=0;i<n;++i){
for(char ch:stickers[i]){
count[i][ch-'a']++;
}
}
unordered_map<string,int> mp;
mp[""]=0;
return dfs(count,target,mp);
}
int dfs(vector<vector<int>> &count,string target,unordered_map<string,int> &mp){
if(mp.count(target)) {
return mp[target];
}
vector<int> tar(26,0);
for(char ch:target){
tar[ch-'a']++;
}
mp[target] = INT_MAX;
for(int i=0;i<count.size();++i){
if(count[i][target[0]-'a'] == 0){
continue;
}
string rest = "";
for(int j=0;j<26;++j){
if(tar[j]-count[i][j]>0){
rest += string(tar[j]-count[i][j],'a'+j);
}
}
int rest_res = dfs(count,rest,mp);
if (rest_res != -1) {
mp[target] = min(mp[target],1+rest_res);
}
}
mp[target] = (mp[target]==INT_MAX?-1:mp[target]);
return mp[target];
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)