You are given a 2D integer array items
where items[i] = [pricei, beautyi]
denotes the price and beauty of an item respectively.
You are also given a 0-indexed integer array queries
. For each queries[j]
, you want to determine the maximum beauty of an item whose price is less than or equal to queries[j]
. If no such item exists, then the answer to this query is 0
.
Return an array answer
of the same length as queries
where answer[j]
is the answer to the jth
query.
Example 1:
Input: items = [[1,2],[3,2],[2,4],[5,6],[3,5]], queries = [1,2,3,4,5,6] Output: [2,4,5,5,6,6] Explanation: - For queries[0]=1, [1,2] is the only item which has price <= 1. Hence, the answer for this query is 2. - For queries[1]=2, the items which can be considered are [1,2] and [2,4]. The maximum beauty among them is 4. - For queries[2]=3 and queries[3]=4, the items which can be considered are [1,2], [3,2], [2,4], and [3,5]. The maximum beauty among them is 5. - For queries[4]=5 and queries[5]=6, all items can be considered. Hence, the answer for them is the maximum beauty of all items, i.e., 6.
Example 2:
Input: items = [[1,2],[1,2],[1,3],[1,4]], queries = [1] Output: [4] Explanation: The price of every item is equal to 1, so we choose the item with the maximum beauty 4. Note that multiple items can have the same price and/or beauty.
Example 3:
Input: items = [[10,1000]], queries = [5] Output: [0] Explanation: No item has a price less than or equal to 5, so no item can be chosen. Hence, the answer to the query is 0.
Constraints:
1 <= items.length, queries.length <= 105
items[i].length == 2
1 <= pricei, beautyi, queries[j] <= 109
This problem asks to find the maximum beauty of an item whose price is less than or equal to each query price. We can efficiently solve this using two main approaches: Sorting + Offline Queries and Sorting + Binary Search.
This approach leverages the power of sorting to optimize the search process.
Algorithm:
Sort: Sort the items
array by price in ascending order. This allows us to iterate through items in increasing price order. Also, sort the queries by price to process them efficiently.
Iterate and Update: Iterate through the sorted queries. For each query q
, maintain a pointer i
to iterate through the sorted items
. As long as the price of the current item (items[i][0]
) is less than or equal to q
, update the maximum beauty seen so far (mx
) and increment i
. The mx
value after this inner loop represents the maximum beauty for the current query q
.
Store Results: Store the mx
value for each query in the ans
array.
Time Complexity: O(n log n + m log m), where n is the length of items
and m is the length of queries
. This is dominated by the sorting operations.
Space Complexity: O(m), where m is the length of queries
, to store the results.
This approach utilizes binary search to efficiently find the maximum beauty for each query.
Algorithm:
Sort: Sort the items
array by price.
Preprocessing: Iterate through the sorted items
. For each item, update its beauty to be the maximum beauty seen so far (including the current item's beauty). This preprocessing step creates a cumulative maximum beauty for each price point.
Binary Search: For each query q
, perform a binary search on the sorted items
to find the largest index j
such that items[j][0] <= q
. The beauty of this item (items[j][1]
) is the maximum beauty for the query q
. Handle the case where no item satisfies the condition (result is 0).
Time Complexity: O((n + m) log n). Sorting takes O(n log n). The preprocessing step takes O(n). The binary search for each query takes O(log n), resulting in O(m log n) for all queries.
Space Complexity: O(n) to store the sorted items (and possibly an additional array for prices if not modifying the original items
array in place).
Approach 1:
def maximumBeauty(items: List[List[int]], queries: List[int]) -> List[int]:
items.sort()
n, m = len(items), len(queries)
ans = [0] * len(queries)
i = mx = 0
for q, j in sorted(zip(queries, range(m))):
while i < n and items[i][0] <= q:
mx = max(mx, items[i][1])
i += 1
ans[j] = mx
return ans
Approach 2:
import bisect
def maximumBeauty(items: List[List[int]], queries: List[int]) -> List[int]:
items.sort()
prices = [p for p, _ in items]
n = len(items)
mx = [items[0][1]]
for i in range(1, n):
mx.append(max(mx[i - 1], items[i][1]))
ans = []
for q in queries:
j = bisect_right(prices, q) - 1
ans.append(0 if j < 0 else mx[j])
return ans
The choice between these approaches depends on the specific input sizes and performance requirements. For very large input, Approach 1 might be slightly faster because it avoids the overhead of binary search on every query. However, Approach 2's clear separation of sorting, preprocessing, and searching often makes it easier to understand and maintain. Both approaches provide significant performance improvements over naive brute-force solutions.