Supermarket Savings
You are preparing for a camping trip and need to purchase groceries from a supermarket. Each product in the store belongs to a specific department (e.g., "Dairy", "Produce", "Pantry").
You are given:
- A 2D list
products, where each element is a pair[productName, department]representing a product and its corresponding department. - A list
shoppingList, which contains the names of products you plan to buy.
Normally, you would buy products following the order in shoppingList. This might require revisiting the same department multiple times. To save time, you decide to group your purchases by department: you collect all products from one department before moving to the next, minimizing department switches.
Return the number of department visits you save by using this grouped strategy compared to shopping strictly in the order of the shoppingList.
Note:
- A "visit" is counted every time you enter a department. Moving between two products in the same department consecutively counts as only one visit.
- The grouped strategy involves visiting each unique department represented in your
shoppingListexactly once.
Example 1
Input
products = [["Cheese", "Dairy"], ["Carrots", "Produce"], ["Potatoes", "Produce"], ["Canned Tuna", "Pantry"], ["Romaine Lettuce", "Produce"], ["Chocolate Milk", "Dairy"], ["Flour", "Pantry"], ["Iceberg Lettuce", "Produce"], ["Coffee", "Pantry"], ["Pasta", "Pantry"], ["Milk", "Dairy"], ["Blueberries", "Produce"], ["Pasta Sauce", "Pantry"]] shoppingList = ["Blueberries", "Milk", "Coffee", "Flour", "Cheese", "Carrots"]Output
2Explanation
**1. Identify Departments:** - Blueberries: Produce - Milk: Dairy - Coffee: Pantry - Flour: Pantry - Cheese: Dairy - Carrots: Produce **2. Original Sequence:** Produce → Dairy → Pantry → Pantry → Dairy → Produce. Consecutive duplicates (Pantry → Pantry) count as one visit. The sequence of visits is: Produce (1) → Dairy (2) → Pantry (3) → Dairy (4) → Produce (5). Total = 5. **3. Grouped Strategy:** Since there are 3 unique departments (Produce, Dairy, Pantry), you visit each exactly once. Total = 3. **4. Calculation:** 5 - 3 = 2.
Example 2
Input
products = [["Apple", "Produce"], ["Bread", "Bakery"]], shoppingList = ["Apple", "Bread"]Output
0Explanation
Original visits: 2 (Produce → Bakery). Grouped visits: 2. Savings: 0.
Example 3
Input
products = [["A", "X"], ["B", "Y"], ["C", "X"]], shoppingList = ["A", "B", "C", "A"]Output
2Explanation
Original departments: X → Y → X → X. Consecutive X's merge. Visits: X, Y, X (3 visits). Unique departments: X, Y (2 visits). Savings: 3 - 2 = 1. Wait, let's re-evaluate: [A(X), B(Y), C(X), A(X)]. Original: X, Y, X (3 visits). Unique: X, Y (2 visits). 3 - 2 = 1.
Constraints
1 <= products.length <= 10⁴1 <= shoppingList.length <= 10⁴- All product names in
shoppingListexist inproducts.
Supermarket Savings
Overview
The problem asks us to compare two different shopping strategies:
- Sequential Strategy: Following the
shoppingListexactly as written. - Grouped Strategy: Grouping all items by their department so that each unique department is visited exactly once.
A "visit" occurs when you enter a department. If two consecutive items on your list are in the same department, it only counts as one visit. The goal is to calculate the difference in the number of visits between these two strategies.
Brute Force
In a brute force approach, we can directly simulate the shopping process. To do this efficiently, we first need a way to quickly look up which department a product belongs to. We can use a dictionary to map each productName to its department.
For the Sequential Strategy, we iterate through the shoppingList and keep track of the "current" department. Every time the department changes from the previous item, we increment our visit counter.
For the Grouped Strategy, the problem statement simplifies this: we visit each unique department exactly once. Therefore, the number of visits is simply the count of unique departments present in the shoppingList.
def supermarket_savings(products: list[list[str]], shoppingList: list[str]) -> int:
# Map products to departments
prod_to_dept = {}
for name, dept in products:
prod_to_dept[name] = dept
# Calculate Sequential visits
sequential_visits = 0
last_dept = None
# We need to find the departments for each item in the shopping list
dept_sequence = []
for item in shoppingList:
dept_sequence.append(prod_to_dept[item])
for dept in dept_sequence:
if dept != last_dept:
sequential_visits += 1
last_dept = dept
# Calculate Grouped visits (number of unique departments in the shopping list)
unique_depts = set(dept_sequence)
grouped_visits = len(unique_depts)
return sequential_visits - grouped_visits
Time complexity: O(N + M) — Where N is the number of products and M is the length of the shopping list; we iterate through both lists to build the map and the department sequence. Space complexity: O(N + M) — We store a dictionary of N products and a sequence list of M departments.
Optimal Approach
The optimal approach follows the same logic as the brute force but focuses on memory efficiency and clean iteration. We don't need to store the entire dept_sequence list. Instead, we can calculate the sequential_visits and identify unique departments in a single pass over the shoppingList.
- Map Creation: Create a hash map (dictionary) for $O(1)$ lookups of department names.
- Single Pass: Iterate through the
shoppingList.- Maintain a
setto track unique departments encountered. - Compare the current item's department with the
previous_deptvariable to count transitions.
- Maintain a
- Result: Subtract the size of the unique departments set from the sequential visit count.
def supermarket_savings(products: list[list[str]], shoppingList: list[str]) -> int:
# Quick lookup for product departments
mapping = {name: dept for name, dept in products}
sequential_visits = 0
unique_depts = set()
prev_dept = None
for item in shoppingList:
current_dept = mapping[item]
# Track unique departments for the Grouped Strategy
unique_depts.add(current_dept)
# Increment visits only if we switch departments
if current_dept != prev_dept:
sequential_visits += 1
prev_dept = current_dept
return sequential_visits - len(unique_depts)
Time complexity: O(N + M) — We perform one pass over the products list to create the map and one pass over the shopping list. Space complexity: O(N + D) — We store N products in the dictionary and D unique departments in a set (where D ≤ M).
Why this works
The logic relies on the definition of a "visit." In the sequential version, the sequence ["Dairy", "Dairy", "Produce"] results in 2 visits because the transition from Dairy to Dairy is ignored. Mathematically, this is equivalent to counting blocks of identical consecutive elements. In the grouped version, we are guaranteed the minimum possible visits, which is exactly one visit per unique department required.
Fast
Comments on the solution
No comments on the solution yet. Start a thread about the editorial or your own approach.
No comments yet for Supermarket Savings. Be the first to start the thread.
No submissions recorded for this problem yet. Use Submit in the editor — each judge run is stored here.
Output
Input
Expected
Your output
Run to see your output.