Cheapest Menu Combinations
Problem
You are given a restaurant `menu` and a list of requested items `userWants`.
Each menu entry is `[id, price, items]` where:
- `id` is a unique string identifier
- `price` is a decimal price as a string (e.g. `"5.00"`)
- `items` is a comma-separated list of item names on that entry (no required spaces)
Implement class `Solution`:
- `Solution()` Initialize the solver (no arguments).
- `string[][] getCheapestCombinations(string[][] menu, string[] userWants)` Return every unique combination of menu entry IDs that covers **all** items in `userWants` at the **minimum total cost**.
Rules:
- Extra items on a menu entry may be ignored.
- A combination is a set of menu IDs (order of selection does not matter).
- Within each combination, return IDs in ascending lexicographic order.
- Return the list of combinations sorted lexicographically (compare ID lists left-to-right).
- If the order cannot be fulfilled, return an empty list `[]`.
Constraints:
- `1 <= menu.length <= 15`
- `1 <= userWants.length <= 15`
- Menu IDs are unique; prices are positive.
- Item names are non-empty strings; `userWants` may contain duplicates (treat as a set of required items).
Example:
```
menu = [
["1", "5.00", "pizza"],
["2", "8.00", "sandwich,coke"],
["3", "4.00", "pasta"],
["4", "2.00", "coke"],
["5", "6.00", "pasta,coke,pizza"],
["6", "8.00", "burger,coke,pizza"],
["7", "5.00", "sandwich"]
]
userWants = ["sandwich", "pasta", "coke"]
```
Output: `[["3", "4", "7"], ["5", "7"]]`
Both combinations cost `11.00`. IDs `3+4+7` cover pasta, coke, and sandwich; IDs `5+7` also cover every requested item (extra pizza ignored).
Common follow-ups
- How would you scale this if menu.length is hundreds instead of ~15?
- What if prices can be zero or negative promotional discounts?
- How would you rank ties by fewest menu entries instead of listing all min-cost combinations?
- How would you support quantity constraints (need two sandwiches)?
Step-by-step study guide
Step 1: Clarify
You must cover every distinct item in `userWants`. Menu entries can over-deliver items. Among all covering subsets of the menu, keep only those with the smallest summed price, then return their ID sets in a canonical sorted form.
Ask: Are IDs always unique? Can the same item appear on many dishes? Is `userWants` a multiset or a set? (Here: set of required items.)
Step 2: Trace the example
Required: sandwich, pasta, coke.
Useful dishes (those that contribute at least one required item):
| ID | Price | Covers | |----|-------|--------| | 2 | 8 | sandwich, coke | | 3 | 4 | pasta | | 4 | 2 | coke | | 5 | 6 | pasta, coke | | 6 | 8 | coke | | 7 | 5 | sandwich |
Min-cost covers at 11: `{3,4,7}` and `{5,7}`. Dish 1 (pizza only) never helps.
Step 3: Brute force
Enumerate all `2^n` subsets of menu entries (`n <= 15`). For each subset, compute the union of items and total cost. Track the minimum cost and collect matching ID lists. Sort for the required output order.
Step 4: Speed up with bitmasks
Map each distinct wanted item to a bit. Convert every dish to `(id, price, mask)`. A subset is valid when OR of masks equals the full mask. Comparing costs with money: use floats carefully or work in integer cents.
Optional DP: `dp[mask] = min cost to achieve coverage mask`, plus store predecessor/lists of ways — useful when you only need one answer, heavier when you need all min-cost combinations.
Step 5: Implement carefully
- Skip dishes whose mask is 0 (no overlap with `userWants`).
- Deduplicate combinations (same ID set found once).
- Sort each ID list, then sort the list of lists.
- Impossible → `[]`.
Step 6: Complexity
- Time: `O(2^n * n)` for subset enumeration with `n = menu.length` (after filtering irrelevant dishes).
- Space: `O(n + number of answers)`.
Step 7: Follow-ups
For larger `n`, use meet-in-the-middle, branch-and-bound on cost, or integer-linear / set-cover heuristics. For quantities, expand bits or use a count vector instead of a bitmask.
Practice
Sign in to unlock practice
Create a free account for full access through 2027 — study guides, follow-ups, and an in-browser code editor. Part of our AI bubble promotion; feedback is appreciated.