1333. Filter Restaurants by Vegan-Friendly, Price and Distance
Problem Description
You are given an array of restaurants where each restaurant is represented as restaurants[i] = [id_i, rating_i, veganFriendly_i, price_i, distance_i]
. Each restaurant has:
id_i
: unique identifier for the restaurantrating_i
: rating of the restaurantveganFriendly_i
: 1 if the restaurant is vegan-friendly, 0 otherwiseprice_i
: price level of the restaurantdistance_i
: distance to the restaurant
You need to filter the restaurants based on three criteria:
- veganFriendly filter: If set to 1 (true), only include restaurants where
veganFriendly_i = 1
. If set to 0 (false), include all restaurants regardless of their vegan-friendly status. - maxPrice filter: Only include restaurants where
price_i <= maxPrice
- maxDistance filter: Only include restaurants where
distance_i <= maxDistance
After filtering, return an array containing only the IDs of the qualifying restaurants, sorted by:
- Primary sort: Rating in descending order (highest rating first)
- Secondary sort: For restaurants with the same rating, sort by ID in descending order (highest ID first)
The solution approach sorts all restaurants by rating and ID in descending order first. Then it iterates through the sorted list, checking each restaurant against the three filter conditions. If a restaurant passes all filters (vegan status meets or exceeds the requirement, price is within limit, and distance is within limit), its ID is added to the result list. The key insight is that vegan >= veganFriendly
handles both cases: when veganFriendly = 1
, only vegan restaurants (with value 1) pass; when veganFriendly = 0
, all restaurants pass since both 0 and 1 are >= 0
.
Intuition
The problem asks us to filter restaurants based on certain criteria and then return their IDs in a specific order. The natural approach is to think about this in two steps: filtering and sorting.
For the filtering part, we need to check three conditions for each restaurant. The tricky part is the vegan-friendly filter. When veganFriendly = 1
, we only want vegan restaurants. When veganFriendly = 0
, we want all restaurants. Instead of writing an if-else statement, we can use a clever comparison: vegan >= veganFriendly
. This works because:
- When
veganFriendly = 1
, only restaurants withvegan = 1
will satisfy1 >= 1
- When
veganFriendly = 0
, bothvegan = 0
andvegan = 1
will satisfy the condition since both0 >= 0
and1 >= 0
are true
For the sorting requirement, we need restaurants ordered by rating (highest first), and ties broken by ID (highest first). Python's sort is stable, so we can sort once using both criteria. The key insight is to use negative values in the sort key (-x[1], -x[0])
to achieve descending order for both rating and ID.
By sorting first before filtering, we ensure that as we iterate through the restaurants and add qualifying ones to our result list, they're already in the correct order. This eliminates the need to sort the filtered results separately, making the solution more efficient and cleaner.
Learn more about Sorting patterns.
Solution Approach
The solution uses a straightforward filtering and sorting approach:
-
Sort the restaurants array: We sort the entire restaurants list using a custom key function
lambda x: (-x[1], -x[0])
. This sorts by:-x[1]
: Negative rating (index 1) for descending order by rating-x[0]
: Negative ID (index 0) for descending order by ID when ratings are equal
This ensures higher-rated restaurants come first, and among restaurants with the same rating, those with higher IDs come first.
-
Initialize result list: Create an empty list
ans
to store the IDs of qualifying restaurants. -
Iterate and filter: Loop through each restaurant in the sorted list. For each restaurant, we destructure it into its components:
for idx, _, vegan, price, dist in restaurants:
The underscore
_
is used for the rating since we don't need it in the filtering logic (we already sorted by it). -
Apply filter conditions: Check if the restaurant meets all three criteria:
vegan >= veganFriendly
: Handles both vegan-only filtering (whenveganFriendly = 1
) and no vegan filtering (whenveganFriendly = 0
)price <= maxPrice
: Ensures the price is within the maximum alloweddist <= maxDistance
: Ensures the distance is within the maximum allowed
-
Collect qualifying IDs: If a restaurant passes all filters, append its ID (
idx
) to the result list. -
Return the result: Since we sorted before filtering, the IDs in
ans
are already in the correct order (by rating descending, then by ID descending for ties).
The time complexity is O(n log n)
due to sorting, where n
is the number of restaurants. The space complexity is O(n)
in the worst case when all restaurants pass the filters.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate the solution approach.
Input:
- restaurants = [[1,4,1,40,10], [2,8,0,50,5], [3,8,1,30,4], [4,10,0,10,3], [5,1,1,15,1]]
- veganFriendly = 1
- maxPrice = 50
- maxDistance = 10
Each restaurant is [id, rating, veganFriendly, price, distance].
Step 1: Sort restaurants by rating (desc), then by id (desc)
Before sorting:
- Restaurant 1: [1,4,1,40,10] - rating=4, id=1
- Restaurant 2: [2,8,0,50,5] - rating=8, id=2
- Restaurant 3: [3,8,1,30,4] - rating=8, id=3
- Restaurant 4: [4,10,0,10,3] - rating=10, id=4
- Restaurant 5: [5,1,1,15,1] - rating=1, id=5
After sorting by (-rating, -id):
- [4,10,0,10,3] - rating=10 (highest)
- [3,8,1,30,4] - rating=8, id=3 (higher id than 2)
- [2,8,0,50,5] - rating=8, id=2
- [1,4,1,40,10] - rating=4
- [5,1,1,15,1] - rating=1 (lowest)
Step 2: Apply filters to each restaurant in sorted order
Restaurant 4 [4,10,0,10,3]:
- vegan=0 >= veganFriendly=1? NO (0 >= 1 is false)
- Skip this restaurant
Restaurant 3 [3,8,1,30,4]:
- vegan=1 >= veganFriendly=1? YES (1 >= 1 is true)
- price=30 <= maxPrice=50? YES
- distance=4 <= maxDistance=10? YES
- Add id=3 to result
Restaurant 2 [2,8,0,50,5]:
- vegan=0 >= veganFriendly=1? NO (0 >= 1 is false)
- Skip this restaurant
Restaurant 1 [1,4,1,40,10]:
- vegan=1 >= veganFriendly=1? YES (1 >= 1 is true)
- price=40 <= maxPrice=50? YES
- distance=10 <= maxDistance=10? YES
- Add id=1 to result
Restaurant 5 [5,1,1,15,1]:
- vegan=1 >= veganFriendly=1? YES (1 >= 1 is true)
- price=15 <= maxPrice=50? YES
- distance=1 <= maxDistance=10? YES
- Add id=5 to result
Step 3: Return result Result = [3, 1, 5]
The restaurants are ordered by rating (8, 4, 1) and the IDs maintain this order. Note how the vegan filter condition vegan >= veganFriendly
elegantly filtered out non-vegan restaurants (id=4 and id=2) since we required veganFriendly=1.
Solution Implementation
1from typing import List
2
3
4class Solution:
5 def filterRestaurants(
6 self,
7 restaurants: List[List[int]],
8 veganFriendly: int,
9 maxPrice: int,
10 maxDistance: int,
11 ) -> List[int]:
12 """
13 Filter and sort restaurants based on given criteria.
14
15 Args:
16 restaurants: List of restaurants where each restaurant is
17 [id, rating, veganFriendly, price, distance]
18 veganFriendly: 1 if only vegan-friendly restaurants should be included, 0 otherwise
19 maxPrice: Maximum acceptable price
20 maxDistance: Maximum acceptable distance
21
22 Returns:
23 List of restaurant IDs sorted by rating (desc) then by ID (desc)
24 """
25 # Sort restaurants by rating (descending) and then by ID (descending)
26 # x[1] is rating, x[0] is restaurant ID
27 restaurants.sort(key=lambda restaurant: (-restaurant[1], -restaurant[0]))
28
29 # Store filtered restaurant IDs
30 filtered_ids = []
31
32 # Iterate through sorted restaurants and apply filters
33 for restaurant_id, rating, is_vegan, price, distance in restaurants:
34 # Check if restaurant meets all criteria:
35 # - Vegan requirement: restaurant's vegan status >= required vegan status
36 # - Price constraint: restaurant's price <= maximum price
37 # - Distance constraint: restaurant's distance <= maximum distance
38 if (is_vegan >= veganFriendly and
39 price <= maxPrice and
40 distance <= maxDistance):
41 filtered_ids.append(restaurant_id)
42
43 return filtered_ids
44
1class Solution {
2 /**
3 * Filters and sorts restaurants based on given criteria.
4 *
5 * @param restaurants 2D array where each row contains [id, rating, veganFriendly, price, distance]
6 * @param veganFriendly 1 if only vegan-friendly restaurants should be included, 0 otherwise
7 * @param maxPrice Maximum acceptable price
8 * @param maxDistance Maximum acceptable distance
9 * @return List of restaurant IDs sorted by rating (descending) then by ID (descending)
10 */
11 public List<Integer> filterRestaurants(
12 int[][] restaurants, int veganFriendly, int maxPrice, int maxDistance) {
13
14 // Sort restaurants by rating (descending), then by ID (descending) if ratings are equal
15 Arrays.sort(restaurants, (restaurantA, restaurantB) -> {
16 // Compare by rating first (index 1)
17 if (restaurantA[1] == restaurantB[1]) {
18 // If ratings are equal, sort by ID in descending order (index 0)
19 return restaurantB[0] - restaurantA[0];
20 }
21 // Sort by rating in descending order
22 return restaurantB[1] - restaurantA[1];
23 });
24
25 // Initialize result list to store filtered restaurant IDs
26 List<Integer> filteredRestaurantIds = new ArrayList<>();
27
28 // Iterate through sorted restaurants and apply filters
29 for (int[] restaurant : restaurants) {
30 int id = restaurant[0];
31 int rating = restaurant[1];
32 int isVeganFriendly = restaurant[2];
33 int price = restaurant[3];
34 int distance = restaurant[4];
35
36 // Check if restaurant meets all filtering criteria
37 boolean meetsVeganRequirement = isVeganFriendly >= veganFriendly;
38 boolean withinPriceRange = price <= maxPrice;
39 boolean withinDistance = distance <= maxDistance;
40
41 if (meetsVeganRequirement && withinPriceRange && withinDistance) {
42 filteredRestaurantIds.add(id);
43 }
44 }
45
46 return filteredRestaurantIds;
47 }
48}
49
1class Solution {
2public:
3 vector<int> filterRestaurants(vector<vector<int>>& restaurants, int veganFriendly, int maxPrice, int maxDistance) {
4 // Sort restaurants by rating (descending), then by id (descending) if ratings are equal
5 sort(restaurants.begin(), restaurants.end(), [](const vector<int>& restaurant_a, const vector<int>& restaurant_b) {
6 // Compare by rating first (index 1)
7 if (restaurant_a[1] != restaurant_b[1]) {
8 return restaurant_a[1] > restaurant_b[1]; // Higher rating comes first
9 }
10 // If ratings are equal, compare by id (index 0)
11 return restaurant_a[0] > restaurant_b[0]; // Higher id comes first
12 });
13
14 // Store the filtered restaurant ids
15 vector<int> filtered_ids;
16
17 // Iterate through sorted restaurants and filter based on conditions
18 for (const auto& restaurant : restaurants) {
19 // Check if restaurant meets all filter criteria:
20 // restaurant[2]: vegan-friendly status (1 if vegan-friendly, 0 otherwise)
21 // restaurant[3]: price
22 // restaurant[4]: distance
23 if (restaurant[2] >= veganFriendly &&
24 restaurant[3] <= maxPrice &&
25 restaurant[4] <= maxDistance) {
26 // Add restaurant id (index 0) to result
27 filtered_ids.push_back(restaurant[0]);
28 }
29 }
30
31 return filtered_ids;
32 }
33};
34
1/**
2 * Filters and sorts restaurants based on given criteria
3 * @param restaurants - Array of restaurant data [id, rating, veganFriendly, price, distance]
4 * @param veganFriendly - Filter for vegan-friendly restaurants (0 or 1)
5 * @param maxPrice - Maximum acceptable price
6 * @param maxDistance - Maximum acceptable distance
7 * @returns Array of restaurant IDs sorted by rating (desc) and ID (desc)
8 */
9function filterRestaurants(
10 restaurants: number[][],
11 veganFriendly: number,
12 maxPrice: number,
13 maxDistance: number,
14): number[] {
15 // Sort restaurants by rating (descending), then by ID (descending) if ratings are equal
16 restaurants.sort((restaurantA: number[], restaurantB: number[]): number => {
17 const ratingA: number = restaurantA[1];
18 const ratingB: number = restaurantB[1];
19 const idA: number = restaurantA[0];
20 const idB: number = restaurantB[0];
21
22 if (ratingA === ratingB) {
23 return idB - idA;
24 }
25 return ratingB - ratingA;
26 });
27
28 // Initialize result array to store filtered restaurant IDs
29 const filteredRestaurantIds: number[] = [];
30
31 // Iterate through sorted restaurants and apply filters
32 for (const restaurant of restaurants) {
33 const id: number = restaurant[0];
34 const rating: number = restaurant[1];
35 const isVeganFriendly: number = restaurant[2];
36 const price: number = restaurant[3];
37 const distance: number = restaurant[4];
38
39 // Check if restaurant meets all filter criteria
40 const meetsVeganRequirement: boolean = isVeganFriendly >= veganFriendly;
41 const meetsPriceRequirement: boolean = price <= maxPrice;
42 const meetsDistanceRequirement: boolean = distance <= maxDistance;
43
44 if (meetsVeganRequirement && meetsPriceRequirement && meetsDistanceRequirement) {
45 filteredRestaurantIds.push(id);
46 }
47 }
48
49 return filteredRestaurantIds;
50}
51
Time and Space Complexity
Time Complexity: O(n log n)
where n
is the number of restaurants.
- The sorting operation using
restaurants.sort()
takesO(n log n)
time - The for loop iterates through all restaurants once, which takes
O(n)
time - Within the loop, the condition checking and appending operations are
O(1)
- Overall time complexity is dominated by the sorting:
O(n log n) + O(n) = O(n log n)
Space Complexity: O(n)
in the worst case.
- The
sort()
method in Python uses Timsort algorithm which requiresO(n)
auxiliary space in the worst case - The
ans
list can contain at mostn
restaurant IDs if all restaurants meet the filtering criteria, requiringO(n)
space - Total space complexity:
O(n) + O(n) = O(n)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Misunderstanding the Vegan-Friendly Filter Logic
The Pitfall: Many developers incorrectly implement the vegan-friendly filter as an exact equality check:
# INCORRECT implementation if veganFriendly == 1 and is_vegan == 1: # Only checks when filter is on filtered_ids.append(restaurant_id)
or
# INCORRECT implementation if is_vegan == veganFriendly: # Excludes non-vegan when filter is off filtered_ids.append(restaurant_id)
This misses the key requirement: when veganFriendly = 0
, we should include ALL restaurants regardless of their vegan status, not just non-vegan ones.
The Solution:
Use the comparison is_vegan >= veganFriendly
:
- When
veganFriendly = 1
: Only restaurants withis_vegan = 1
pass (1 >= 1 is True, 0 >= 1 is False) - When
veganFriendly = 0
: All restaurants pass (both 1 >= 0 and 0 >= 0 are True)
2. Sorting In-Place Modifies Original Data
The Pitfall:
The current solution sorts the input array in-place with restaurants.sort()
, which modifies the original data structure. This could be problematic if:
- The caller expects the original array to remain unchanged
- The same array is used elsewhere in the program
- You need to preserve the original ordering for any reason
The Solution: Create a copy of the array before sorting:
# Create a sorted copy instead of modifying in-place
sorted_restaurants = sorted(restaurants, key=lambda x: (-x[1], -x[0]))
for restaurant_id, rating, is_vegan, price, distance in sorted_restaurants:
# ... rest of the filtering logic
3. Incorrect Sorting Order
The Pitfall: Forgetting to negate values for descending order or mixing up the indices:
# INCORRECT - sorts in ascending order restaurants.sort(key=lambda x: (x[1], x[0])) # INCORRECT - wrong indices (ID is at index 0, rating at index 1) restaurants.sort(key=lambda x: (-x[0], -x[1]))
The Solution: Always verify:
- Index 0 is the restaurant ID
- Index 1 is the rating
- Use negative values for descending order:
(-x[1], -x[0])
- Primary sort key comes first in the tuple (rating), secondary comes second (ID)
What's the relationship between a tree and a graph?
Recommended Readings
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!