2022-5-14-贴纸拼词

691. 贴纸拼词

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/stickers-to-spell-word
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

[可运行]直观的想法,对于target,我们依次用stickers中的字符串通过剪切去匹配target,方法就是首先看stickers[i]中是否包含target[0](这是一种贪心的想法,如果你没有target[0],我去找下一个字符串,我期望得到可以满足我所有字符的sticker),如果包含,那么把target减去stickers[i]中包含的target的字符的数量,紧接着将其构造为一个新的nowTarget,那么接下来的任务就变成了求nowTarget的最小贴纸数量。任务和子任务的定义是相同的,我们用递归来实现,递归的边界就是完全匹配,也就是nowTarget变为""。

class Solution {
public:
	int minStickers(vector<string>& stickers, string target) {
		int stickersSize = stickers.size();
        //target需要的最少贴纸数量
		unordered_map<string, int> strStickerCnt;
        //各个贴纸中各个字母出现的次数
        vector<vector<int>> myStickers(stickersSize, vector<int>(26, 0));
		for (int i = 0; i < stickersSize; ++i)
			for (char ch : stickers[i])  myStickers[i][ch - 'a'] += 1;
		//初始化,空字符串不需要贴纸
        strStickerCnt[""] = 0;
        //返回拼凑target需要的最少贴纸数量
		return dfs(strStickerCnt, myStickers, target);
	}

	int dfs(unordered_map<string, int>& strStickerCnt, vector<vector<int>>& myStickers, string target) {
		//深搜边界,target已经搜索结束
        if (strStickerCnt.count(target)) return strStickerCnt[target];
		int minRes = INT_MAX, stickersSize = myStickers.size();
		//统计target中各个字符出现的次数
		vector<int> tar(26, 0);
		for (char ch : target) tar[ch - 'a'] += 1;
		//尝试使用每一个sticker
		for (int i = 0; i < stickersSize; ++i) {
			//当前sticker中没有target[0]这个字符
			if (myStickers[i][target[0] - 'a'] == 0) continue;
			//nowTarget为使用sticker[i]后剩余的字母
			string nowTarget = "";
			for (int j = 0; j < 26; j++)
				if (tar[j] - myStickers[i][j] > 0)
					nowTarget += string(tar[j] - myStickers[i][j], 'a' + j);
			//任务转换为搜索nowTarget需要的最少贴纸数
			int tempRes = dfs(strStickerCnt, myStickers, nowTarget);
			//更新target字符串需要的最少贴纸数
			if (tempRes != -1) minRes = min(minRes, 1 + tempRes);
		}
        //对上一层的反馈,是否找到了一套贴纸方案,是则返回贴纸数目,否则返回-1
    	strStickerCnt[target] = minRes == INT_MAX ? -1 : minRes;
        //for (auto iter = strStickerCnt.begin(); iter != strStickerCnt.end(); ++iter) {
        //    cout << iter->first << " " << iter->second;
        }
        cout<<endl;
		return strStickerCnt[target];
	}
};

我们针对示例一,看一下函数运行的过程:

 通过不同层中对strStickerCnt的输出我们可以看到,匹配的过程是:"" 0 -> "ht" 1 -> aeht 2 -> thehat 3

所用到的标签从前往后是:with -> example -> with

参考资料:LeetCode 贴纸拼词(回溯法+备忘录)_hestyle的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jiawen9

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值