Solution with explanation and tips for optimize
IntuitionThis problem can be viewed as a Multi-Source BFS problem. Starting from water cells, the algorithm gradually spreads out to unvisited land cells until
# Intuition
This problem can be viewed as a **Multi-Source BFS** problem. Starting from water cells, the algorithm gradually spreads out to unvisited land cells until all regions are filled.

> **Tips**: This problem can easily result in timeouts or excessive memory usage. Below are some optimizations:
> 1. Use a simplified sliding window direction array. It reduces the size from 4 x 2 to 5 x 1 (moving once and taking two elements, still covering four directions).
> 2. Use `nextQueue` to store the points for the next BFS level, reducing the performance overhead caused by `unshift`.

# Approach

### Step 1: Directions and Record Map Dimensions

```typescript
// Direction array for moving north, east, south, and west
// This uses a sliding window technique for less memory usage
const HIGHEST_PEEK_DIRECTIONS: number[] = [0, 1, 0, -1, 0];

const m = isWater.length;    // Number of rows
const n = isWater[0].length; // Number of columns
```

### Step 2: Initialize the Map and Processing Queue

```typescript
// Initialize the map, setting all points' heights to -1, representing unvisited cells
const heights = Array.from({ length: m }, () => Array(n).fill(-1));
let queue: [number, number, number][] = [];
```

### Step 3: Initialize Water Sources

```typescript
// Initialize water sources, set all water cells' heights to 0, and add them to the processing queue
for (let row = 0; row < m; row++) {
  for (let col = 0; col < n; col++) {
    if (isWater[row][col] === 1) {
      heights[row][col] = 0;
      queue.push([row, col, 0]);
    }
  }
}
```

### Step 4: Start BFS

```typescript
while (queue.length > 0) {
  // Mark the points for the next BFS level
  const nextQueue: [number, number, number][] = [];
  
  // Process all points in the current BFS level
  for (const [currentRow, currentCol, currentHeight] of queue) {
    for (let i = 0; i < 4; i++) {
      // Use the sliding window direction array to calculate the position of the next point
      const nextRow = currentRow + HIGHEST_PEEK_DIRECTIONS[i];
      const nextCol = currentCol + HIGHEST_PEEK_DIRECTIONS[i + 1];

      // Skip points that are out of bounds or already visited
      if (
        nextRow < 0 ||
        nextRow >= m ||
        nextCol < 0 ||
        nextCol >= n ||
        heights[nextRow][nextCol] !== -1
      ) {
        continue;
      }

      // Set the height of adjacent points and add them to the next processing queue
      heights[nextRow][nextCol] = currentHeight + 1;
      queue.push([nextRow, nextCol, currentHeight + 1]);
    }
  }
  // Move to the next BFS level
  queue = nextQueue;
}
```

# Complexity

- **Time Complexity**:
  - Initializing water sources: $$O(m \times n)$$
  - BFS traverses all cells, time complexity: $$O(m \times n)$$
  - Total time complexity: $$O(m \times n)$$

  > $$O(m \times n)$$

- **Space Complexity**:
  - An additional 2D array `heights` is used to store the height of each point: $$O(m \times n)$$
  - Queues `queue` and `nextQueue` require space: $$O(m \times n)$$
  - Total space complexity: $$O(m \times n)$$

  > $$O(m \times n)$$

# Code
```typescript []
// Direction array for moving north, east, south, and west
// This uses a sliding window technique for less memory usage
const HIGHEST_PEEK_DIRECTIONS: number[] = [0, 1, 0, -1, 0];

function highestPeak(isWater: number[][]): number[][] {
  const m = isWater.length;
  const n = isWater[0].length;

  const heights = Array.from({ length: m }, () => Array(n).fill(-1));
  let queue: [number, number, number][] = [];
  
  for (let row = 0; row < m; row++) {
    for (let col = 0; col < n; col++) {
      if (isWater[row][col] === 1) {
        heights[row][col] = 0;
        queue.push([row, col, 0]);
      }
    }
  }

  while (queue.length > 0) {
    const nextQueue: [number, number, number][] = [];
    for (const [currentRow, currentCol, currentHeight] of queue) {
      for (let i = 0; i < 4; i++) {
        const nextRow = currentRow + HIGHEST_PEEK_DIRECTIONS[i];
        const nextCol = currentCol + HIGHEST_PEEK_DIRECTIONS[i + 1];

        if (
          nextRow < 0 ||
          nextRow >= m ||
          nextCol < 0 ||
          nextCol >= n ||
          heights[nextRow][nextCol] !== -1
        ) {
          continue;
        }

        heights[nextRow][nextCol] = currentHeight + 1;
        queue.push([nextRow, nextCol, currentHeight + 1]);
      }
    }
    queue = nextQueue;
  }

  return heights;
}
```
['Array', 'Dynamic Programming', 'Breadth-First Search', 'TypeScript']