Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find path with minimum effort in Python
Finding the path with minimum effort involves navigating through a 2D matrix where we need to minimize the maximum absolute difference between consecutive cells. This problem is solved efficiently using Dijkstra's algorithm with a priority queue.
Problem Understanding
Given a 2D matrix heights of size m × n, we start at position (0, 0) and want to reach (m-1, n-1). We can move in four directions: up, down, left, or right. The effort of a path is defined as the maximum absolute difference between consecutive cells along that path.
For example, with the matrix:
| 2 | 3 | 4 |
| 4 | 9 | 5 |
| 6 | 4 | 6 |
The optimal path [2?3?4?5?6] has a maximum difference of 1, so the minimum effort is 1.
Algorithm Approach
We use Dijkstra's algorithm to find the path with minimum effort:
- Use a priority queue (min-heap) to always process the cell with minimum effort first
- Track visited cells to avoid revisiting
- For each cell, explore all four neighbors and calculate the effort needed
- Return the effort when we reach the destination
Implementation
import heapq
def minimum_effort_path(heights):
rows, cols = len(heights), len(heights[0])
# Priority queue: (effort, x, y)
pq = [(0, 0, 0)]
# Track visited cells
visited = set()
# Four directions: down, up, right, left
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
while pq:
current_effort, x, y = heapq.heappop(pq)
# If we reached the destination
if x == rows - 1 and y == cols - 1:
return current_effort
# Skip if already visited
if (x, y) in visited:
continue
# Mark as visited
visited.add((x, y))
# Explore all four neighbors
for dx, dy in directions:
new_x, new_y = x + dx, y + dy
# Check bounds and if not visited
if (0 <= new_x < rows and 0 <= new_y < cols and
(new_x, new_y) not in visited):
# Calculate effort for this move
effort = abs(heights[new_x][new_y] - heights[x][y])
max_effort = max(current_effort, effort)
heapq.heappush(pq, (max_effort, new_x, new_y))
return -1 # Should never reach here for valid input
# Test the function
heights = [[2, 3, 4], [4, 9, 5], [6, 4, 6]]
result = minimum_effort_path(heights)
print(f"Minimum effort required: {result}")
Minimum effort required: 1
How It Works
The algorithm works by:
- Initialization: Start with effort 0 at position (0, 0)
- Priority Processing: Always process the cell with minimum effort first
- Neighbor Exploration: For each cell, check all four neighbors
- Effort Calculation: The effort to reach a neighbor is the maximum of current path effort and the absolute difference between current and neighbor cells
- Termination: Return the effort when destination is reached
Example with Different Matrix
# Test with a more challenging matrix
heights2 = [[1, 2, 1, 1, 1],
[1, 2, 1, 2, 1],
[1, 2, 1, 2, 1],
[1, 2, 1, 2, 1],
[1, 1, 1, 2, 1]]
result2 = minimum_effort_path(heights2)
print(f"Minimum effort for complex matrix: {result2}")
# Edge case: single cell
heights3 = [[0]]
result3 = minimum_effort_path(heights3)
print(f"Single cell effort: {result3}")
Minimum effort for complex matrix: 0 Single cell effort: 0
Time and Space Complexity
| Aspect | Complexity | Explanation |
|---|---|---|
| Time | O(mn log(mn)) | Each cell visited once, heap operations are log(mn) |
| Space | O(mn) | Priority queue and visited set can store all cells |
Conclusion
The minimum effort path problem is efficiently solved using Dijkstra's algorithm with a priority queue. The key insight is treating effort as the "distance" and always processing the path with minimum effort first, ensuring we find the optimal solution.
