input: def shortestPath(grid, k):
      """
      Consider a grid of dimensions N x N (with N being at least 2) and a positive integer k. 
      Each grid cell contains a unique integer value from the range [1, N * N].
  
      Your task is to determine the shortest path of exactly k steps within the grid. 
      Starting from any cell, you can move to any adjacent cell that shares an edge with 
      your current position.
  
      Note that a path of length k entails visiting exactly k cells, and these cells 
      do not have to be distinct. You must remain within the boundaries of the grid.
      
      A path X (of length k) is deemed smaller than another path Y (of length k) 
      if, when you list the values along the paths in sequence (let's call these lst_X and lst_Y), 
      lst_X is lexicographically smaller than lst_Y. This means there exists some index i (1 <= i <= k) 
      such that lst_X[i] < lst_Y[i], and for every j (1 <= j < i), lst_X[j] = lst_Y[j].
  
      The result is guaranteed to be unique.
      Return the values along the cells of the minimal path in ordered sequence.
  
      Examples:
  
          Input: grid = [ [1,2,3], [4,5,6], [7,8,9]], k = 3
          Output: [1, 2, 1]
  
          Input: grid = [ [5,9,3], [4,1,6], [7,8,2]], k = 1
          Output: [1]
      """
output:     from heapq import heappop, heappush
  
      def neighbors(x, y):
          for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
              nx, ny = x + dx, y + dy
              if 0 <= nx < len(grid) and 0 <= ny < len(grid[0]):
                  yield nx, ny
  
      n = len(grid)
      min_heap = []
      
      for i in range(n):
          for j in range(n):
              heappush(min_heap, (grid[i][j], i, j, [grid[i][j]]))
  
      while min_heap:
          val, x, y, path = heappop(min_heap)
          if len(path) == k:
              return path
          for nx, ny in neighbors(x, y):
              heappush(min_heap, (grid[nx][ny], nx, ny, path + [grid[nx][ny]]))