← DSA
HARD

Swim in Rising Water

PracticeNeetCode ↗LeetCode ↗

Given an n×n grid where grid[i][j] is a cell's elevation, water rises over time. At time t you may swim between adjacent cells only if both have elevation ≤ t. Starting at (0,0), return the minimum time needed to reach (n-1, n-1).

Example

Input grid = [[0,2],[1,3]]
Output 3

Key Pointers

Step-by-Step Analysis

  1. Push (grid[0][0], 0, 0) onto a min-heap and mark (0,0) visited.
  2. Pop the cell with the smallest recorded time; if it's the bottom-right cell, that time is the answer.
  3. For each of its unvisited 4-directional neighbors, compute the time to reach it as max(current time, that neighbor's elevation), mark it visited, and push it.
  4. Repeat until the destination is popped off the heap.

Complexity

Time: O(n² log n) — Space: O(n²)

Code

import heapq

def swimInWater(grid: list[list[int]]) -> int:
    n = len(grid)
    visited = [[False] * n for _ in range(n)]
    min_heap = [(grid[0][0], 0, 0)]
    visited[0][0] = True
    directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]

    while min_heap:
        time, r, c = heapq.heappop(min_heap)
        if r == n - 1 and c == n - 1:
            return time

        for dr, dc in directions:
            nr, nc = r + dr, c + dc
            if 0 <= nr < n and 0 <= nc < n and not visited[nr][nc]:
                visited[nr][nc] = True
                heapq.heappush(min_heap, (max(time, grid[nr][nc]), nr, nc))

    return -1

Code Explanation

How the solution above works, piece by piece.

  1. You can swim along a path once the water is at least as high as every cell on it, so a path costs its maximum elevation.
  2. The heap holds (time, r, c): the minimal max-elevation needed to reach that cell so far.
  3. Pop the cell with the lowest time. If it's the bottom-right corner, that time is the answer.
  4. Push each unvisited neighbour with max(time, grid[nr][nc]): the path's max grows only if the new cell is higher.
  5. It's Dijkstra with "max" instead of "+": O(n² log n).

Visual Walkthrough

Running it on grid = [[0, 2], [1, 3]]:

2 by 2 grid with the cheapest route highlighted0213heap pops the reachable cell with thelowest "time needed so far":pop (0,0) t=0 → push (0,1) t=2, (1,0) t=1pop (1,0) t=1 → push (1,1) t=max(1,3)=3pop (0,1) t=2 → nothing newpop (1,1) t=3 → bottom-right → 3
The time to reach a cell along a path is the highest elevation on that path. The min-heap always extends the path whose maximum so far is smallest, so the first time the bottom-right cell is popped, that maximum is the answer.
path used

Video Explanation

NeetCode — Dijkstra's Algorithm, LeetCode 778