You have information about n different recipes. You are given a string array recipes and a 2D string array ingredients. The ith recipe has the name recipes[i], and you can create it if you have all the needed ingredients from ingredients[i]. A recipe can also be an ingredient for other recipes, i.e., ingredients[i] may contain a string that is in recipes.
You are also given a string array supplies containing all the ingredients that you initially have, and you have an infinite supply of all of them.
Return a list of all the recipes that you can create. You may return the answer in any order.
Note that two recipes may contain each other in their ingredients.
Example 1:
Input: recipes = ["bread"], ingredients = [["yeast","flour"]], supplies = ["yeast","flour","corn"]
Output: ["bread"]
Explanation:
We can create "bread" since we have the ingredients "yeast" and "flour".
Example 2:
Input: recipes = ["bread","sandwich"], ingredients = [["yeast","flour"],["bread","meat"]], supplies = ["yeast","flour","meat"]
Output: ["bread","sandwich"]
Explanation:
We can create "bread" since we have the ingredients "yeast" and "flour".
We can create "sandwich" since we have the ingredient "meat" and can create the ingredient "bread".
Example 3:
Input: recipes = ["bread","sandwich","burger"], ingredients = [["yeast","flour"],["bread","meat"],["sandwich","meat","bread"]], supplies = ["yeast","flour","meat"]
Output: ["bread","sandwich","burger"]
Explanation:
We can create "bread" since we have the ingredients "yeast" and "flour".
We can create "sandwich" since we have the ingredient "meat" and can create the ingredient "bread".
We can create "burger" since we have the ingredient "meat" and can create the ingredients "bread" and "sandwich".
Constraints:
n == recipes.length == ingredients.length
1 <= n <= 100
1 <= ingredients[i].length, supplies.length <= 100
1 <= recipes[i].length, ingredients[i][j].length, supplies[k].length <= 10
recipes[i], ingredients[i][j], and supplies[k] consist only of lowercase English letters.
All the values of recipes and supplies combined are unique.
Each ingredients[i] does not contain any duplicate values.
這題給我們三個參考變數,
分別是 recipes, ingredients, supplies
其中 recipes 與 ingredients 共用索引,分別代表食譜名稱與食譜的材料清單;
supplies 代表我們手上現有的材料(份數為無限)。
這題的難點在食譜分級,
舉個例子,常常參加二戰的小夥伴都知道(錯棚了。
常常玩 overcooked 的玩家都知道,
如果你要做漢堡,手上只有麵包、生牛肉跟生菜,
是沒辦法直接組合成一個漢堡出餐的。
你要先把牛肉弄熟、生菜切好。
(是說為什麼麵包不用烤?)
那這邊熟牛肉與切好的生菜,就是高一級的食譜,
你初始沒有的,但是算一算發現其實自己有。
那這邊我第一次寫腦子很簡單,
就 while 迴圈開下去,轉到食譜不會繼續生成嘛。
C++程式碼:
假設 recipes 的種類為 R、ingredients 的種類為 G、supplies 的種類為 S。
計算複雜度:O(R^2 * Sum_Gi)
-> 因為如果是一字長蛇陣,總共有 R 級食譜,即你每次解完一道食譜才能解下一道、環環相扣,
外迴圈就是 O(R^2) ,又因為每道食譜的材料種類不同,所以 O(Sum_Gi)
空間複雜度:O(R + S)
-> 也是因為一字長蛇陣,需要紀錄的 rec 最多會需要 R + S 的記憶體空間
哎呀,我算完看了了 O(R^2) 的計算複雜度,大清要亡了呀!
不行不行,看一下別人怎麼算的?
拓樸排序!
除去技術部分,簡單來說就是紀錄每個食譜還缺幾道原料?
我們用 ind 陣列存起來,並用 DAG 去紀錄每道原料能做什麼食譜、更新當下狀態。
當食譜所缺的原料數量等於零時,恭喜晉級!
這個食譜現在也加入原料區為我們鳳梨披薩王國奮戰!
C++程式碼:
假設 res 的長度為 E。
計算複雜度:O(R + Sum_Gi + S)
-> 每個食譜只會進 queue 一次 O(R)
-> 每個原料序列只會進 queue 一次 O(Sum_Gi)
-> 建立 set O(S)
空間複雜度:O(R + Sum_Gi + S + E)
-> ind O(R)
-> DAG O(Sum_Gi)
-> s O(S)
-> res O(E)
因為不知道 q 會給多少,但肯定每次小於 R 並最大等於 R,就當作 R 來算了。
MurMur:
最近體感很多並查集、拓樸排序na。