拓扑排序
题面
题目链接:2115. 从给定原材料中找到所有可以做出的菜 - 力扣(LeetCode)
你有
n
道不同菜的信息。给你一个字符串数组recipes
和一个二维字符串数组ingredients
。第i
道菜的名字为recipes[i]
,如果你有它 所有 的原材料ingredients[i]
,那么你可以 做出 这道菜。一道菜的原材料可能是 另一道 菜,也就是说ingredients[i]
可能包含recipes
中另一个字符串。同时给你一个字符串数组
supplies
,它包含你初始时拥有的所有原材料,每一种原材料你都有无限多。请你返回你可以做出的所有菜。你可以以 任意顺序 返回它们。
注意两道菜在它们的原材料中可能互相包含。
解题思路
做出一个菜,可以由这个菜作为原料做出另一个,且原料无限
很容易幻想出一个有向图,从原料指向各个目标菜,而拥有公共原料,且之间存在互相作为原料的情况则可以看作图的后序
了解过或者学习过拓扑排序的,到这里应该就能判断谁作为队列的初始元素了
但是题目给出的是原料有哪些,需要做的菜有哪些,它们又各自需要哪些作为原料
所以我们需要用哈希表存储这些关系,避免大量重复的遍历寻找
哈希表1:一个原料能做出哪些菜
哈希表2:一个菜的入度为几(因为每个元素都为string类型,所以也是需要用哈希表)
拓扑排序套路写法
class Solution {
public:vector<string> findAllRecipes(vector<string>& recipes,vector<vector<string>>& ingredients,vector<string>& supplies) {unordered_map<string, int> indegree;unordered_map<string, vector<string>> out;queue<string> q;vector<string> ans;for (string i : supplies)q.push(i);for (int i = 0; i < recipes.size(); i++) {indegree[recipes[i]] = ingredients[i].size();for(string var:ingredients[i]){out[var].push_back(recipes[i]);}}while (!q.empty()) {string now = q.front();q.pop();for(string aim:out[now]){if(--indegree[aim]==0){ans.push_back(aim);q.push(aim);}}}return ans;}
};