Find All Possible Recipes from Given Supplies - Complete Solution Guide
Find All Possible Recipes from Given Supplies is LeetCode problem 2115, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
You have information about n different recipes. You are given a string array recipes and a 2D string array ingredients . The i th 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
Detailed Explanation
The problem asks us to find all possible recipes that can be created from a given set of initial supplies. We are provided with a list of recipes, a list of ingredients required for each recipe, and a list of initial supplies. We can create a recipe if we have all of its ingredients, and a recipe can also be an ingredient for other recipes. The goal is to return a list of all the recipes that can be created, considering the dependencies between recipes.
Solution Approach
The solution uses a topological sort-based approach. It constructs a directed graph where nodes are ingredients and recipes. An edge exists from an ingredient 'x' to a recipe 'y' if 'x' is an ingredient of 'y' and 'x' is not in the `supplies` list. It uses in-degree counting (number of unavailable ingredients) for each recipe. The algorithm initializes a queue with recipes having an in-degree of 0 (meaning all ingredients are available). It then iteratively processes the queue, making recipes and decrementing the in-degree of recipes that depend on the made recipe. If any of those dependent recipe's in-degree becomes 0, it's added to the queue. The process continues until the queue is empty.
Step-by-Step Algorithm
- Step 1: Initialize an adjacency list (`adj`) to store the dependencies between ingredients and recipes. `adj[ingredient]` will contain a list of recipes that require that ingredient but which are not in the initial supplies.
- Step 2: Initialize an in-degree map (`in_degree`) to store the number of unavailable ingredients for each recipe.
- Step 3: Iterate through each recipe and its ingredients. If an ingredient is not in the initial `supplies`, add an edge from that ingredient to the recipe in the adjacency list and increment the recipe's in-degree.
- Step 4: Create a queue and add all recipes with an in-degree of 0 to the queue.
- Step 5: While the queue is not empty, dequeue a recipe. Add this recipe to the `result` list.
- Step 6: Iterate through the adjacency list for the dequeued recipe. For each dependent recipe in the adjacency list, decrement its in-degree. If the in-degree becomes 0, enqueue it.
- Step 7: Return the `result` list of recipes that can be created.
Key Insights
- Insight 1: Topological sorting is the core algorithmic concept. Recipes can be considered as nodes in a directed graph where an edge from ingredient 'a' to recipe 'b' exists if 'a' is an ingredient for 'b'. The problem requires finding all nodes (recipes) that can be reached from the initial supply nodes.
- Insight 2: Representing the dependencies between recipes and ingredients as an adjacency list or a similar graph representation is crucial for efficiently determining which recipes can be made.
- Insight 3: Using in-degree counting to determine the order in which recipes can be made avoids circular dependencies and ensures that a recipe is only made after all its ingredients are available.
Complexity Analysis
Time Complexity: O(n + m)
Space Complexity: O(n + m)
Topics
This problem involves: Array, Hash Table, String, Graph, Topological Sort.
Companies
Asked at: PhonePe, TikTok, Verily.