{x}
blog image

K Highest Ranked Items Within a Price Range

You are given a 0-indexed 2D integer array grid of size m x n that represents a map of the items in a shop. The integers in the grid represent the following:

  • 0 represents a wall that you cannot pass through.
  • 1 represents an empty cell that you can freely move to and from.
  • All other positive integers represent the price of an item in that cell. You may also freely move to and from these item cells.

It takes 1 step to travel between adjacent grid cells.

You are also given integer arrays pricing and start where pricing = [low, high] and start = [row, col] indicates that you start at the position (row, col) and are interested only in items with a price in the range of [low, high] (inclusive). You are further given an integer k.

You are interested in the positions of the k highest-ranked items whose prices are within the given price range. The rank is determined by the first of these criteria that is different:

  1. Distance, defined as the length of the shortest path from the start (shorter distance has a higher rank).
  2. Price (lower price has a higher rank, but it must be in the price range).
  3. The row number (smaller row number has a higher rank).
  4. The column number (smaller column number has a higher rank).

Return the k highest-ranked items within the price range sorted by their rank (highest to lowest). If there are fewer than k reachable items within the price range, return all of them.

 

Example 1:

Input: grid = [[1,2,0,1],[1,3,0,1],[0,2,5,1]], pricing = [2,5], start = [0,0], k = 3
Output: [[0,1],[1,1],[2,1]]
Explanation: You start at (0,0).
With a price range of [2,5], we can take items from (0,1), (1,1), (2,1) and (2,2).
The ranks of these items are:
- (0,1) with distance 1
- (1,1) with distance 2
- (2,1) with distance 3
- (2,2) with distance 4
Thus, the 3 highest ranked items in the price range are (0,1), (1,1), and (2,1).

Example 2:

Input: grid = [[1,2,0,1],[1,3,3,1],[0,2,5,1]], pricing = [2,3], start = [2,3], k = 2
Output: [[2,1],[1,2]]
Explanation: You start at (2,3).
With a price range of [2,3], we can take items from (0,1), (1,1), (1,2) and (2,1).
The ranks of these items are:
- (2,1) with distance 2, price 2
- (1,2) with distance 2, price 3
- (1,1) with distance 3
- (0,1) with distance 4
Thus, the 2 highest ranked items in the price range are (2,1) and (1,2).

Example 3:

Input: grid = [[1,1,1],[0,0,1],[2,3,4]], pricing = [2,3], start = [0,0], k = 3
Output: [[2,1],[2,0]]
Explanation: You start at (0,0).
With a price range of [2,3], we can take items from (2,0) and (2,1). 
The ranks of these items are: 
- (2,1) with distance 5
- (2,0) with distance 6
Thus, the 2 highest ranked items in the price range are (2,1) and (2,0). 
Note that k = 3 but there are only 2 reachable items within the price range.

 

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 105
  • 1 <= m * n <= 105
  • 0 <= grid[i][j] <= 105
  • pricing.length == 2
  • 2 <= low <= high <= 105
  • start.length == 2
  • 0 <= row <= m - 1
  • 0 <= col <= n - 1
  • grid[row][col] > 0
  • 1 <= k <= m * n

Solution Explanation:

This problem requires finding the k highest-ranked items within a given price range in a grid, considering distance, price, row, and column as ranking criteria. The solution uses a Breadth-First Search (BFS) algorithm coupled with sorting to efficiently achieve this.

Approach:

  1. BFS for Traversal: A BFS algorithm systematically explores the grid starting from the given start position. It keeps track of the distance from the start position for each reachable cell.

  2. Price Range Filtering: During the BFS, only cells containing items within the specified price range (pricing[0] to pricing[1]) are considered.

  3. Storing Ranked Items: For each item within the price range, its distance, price, row, and column are stored in a data structure (like a list of tuples or a custom class in object-oriented languages). This data structure maintains the rank information of each item.

  4. Sorting: After the BFS is complete, the stored item data is sorted based on the ranking criteria (distance, then price, then row, then column).

  5. Returning Top k Items: Finally, the top k items from the sorted list are returned as a list of coordinates.

Time Complexity Analysis:

  • BFS: The BFS traversal visits each cell in the grid at most once. Therefore, the time complexity of the BFS part is O(m*n), where 'm' and 'n' are the dimensions of the grid.
  • Sorting: Sorting the list of items takes O((mn) * log(mn)) in the worst case (if nearly all cells contain items within the price range). This dominates the time complexity.

Space Complexity Analysis:

  • Queue (BFS): In the worst case, the BFS queue can hold all cells in the grid, resulting in O(m*n) space complexity.
  • Sorted List: The list storing item data can also hold up to all cells in the grid, leading to O(m*n) space complexity.

Therefore, the overall time complexity is O((mn) * log(mn)), and the space complexity is O(m*n).

Code Implementation (Python3):

from collections import deque
from itertools import pairwise
 
class Solution:
    def highestRankedKItems(
        self, grid: List[List[int]], pricing: List[int], start: List[int], k: int
    ) -> List[List[int]]:
        m, n = len(grid), len(grid[0])
        row, col = start
        low, high = pricing
        q = deque([(row, col, 0)]) # (row, col, distance)
        visited = set()
        visited.add((row, col))
        pq = [] # list to store (distance, price, row, col)
 
        while q:
            r, c, dist = q.popleft()
            price = grid[r][c]
            if low <= price <= high:
                pq.append((dist, price, r, c))
 
            for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
                nr, nc = r + dr, c + dc
                if 0 <= nr < m and 0 <= nc < n and grid[nr][nc] > 0 and (nr, nc) not in visited:
                    q.append((nr, nc, dist + 1))
                    visited.add((nr, nc))
 
 
        pq.sort() #sort by distance, price, row, col
        result = []
        for i in range(min(k, len(pq))):
            result.append([pq[i][2], pq[i][3]])
        return result
 

Other Languages: The solution can be implemented similarly in Java, C++, Go, TypeScript, and other languages using their respective data structures and sorting functions. The core algorithm remains the same. The provided solution in the question already contains implementations in Java, C++, Go, and TypeScript.