Skip to content

Commit 822987f

Browse files
committed
leetcode
1 parent 532ad3a commit 822987f

File tree

3 files changed

+563
-0
lines changed

3 files changed

+563
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
3+
-* 1631. Path With Minimum Effort *-
4+
5+
You are a hiker preparing for an upcoming hike. You are given heights, a 2D array of size rows x columns, where heights[row][col] represents the height of cell (row, col). You are situated in the top-left cell, (0, 0), and you hope to travel to the bottom-right cell, (rows-1, columns-1) (i.e., 0-indexed). You can move up, down, left, or right, and you wish to find a route that requires the minimum effort.
6+
7+
A route's effort is the maximum absolute difference in heights between two consecutive cells of the route.
8+
9+
Return the minimum effort required to travel from the top-left cell to the bottom-right cell.
10+
11+
12+
13+
Example 1:
14+
15+
16+
17+
Input: heights = [[1,2,2],[3,8,2],[5,3,5]]
18+
Output: 2
19+
Explanation: The route of [1,3,5,3,5] has a maximum absolute difference of 2 in consecutive cells.
20+
This is better than the route of [1,2,2,2,5], where the maximum absolute difference is 3.
21+
Example 2:
22+
23+
24+
25+
Input: heights = [[1,2,3],[3,8,4],[5,3,5]]
26+
Output: 1
27+
Explanation: The route of [1,2,3,4,5] has a maximum absolute difference of 1 in consecutive cells, which is better than route [1,3,5,3,5].
28+
Example 3:
29+
30+
31+
Input: heights = [[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]]
32+
Output: 0
33+
Explanation: This route does not require any effort.
34+
35+
36+
Constraints:
37+
38+
rows == heights.length
39+
columns == heights[i].length
40+
1 <= rows, columns <= 100
41+
1 <= heights[i][j] <= 106
42+
43+
44+
*/
45+
46+
import 'dart:math';
47+
48+
class Di {
49+
List<List<int>> effort = List.generate(105, (_) => List<int>.filled(105, 0));
50+
List<int> dx = [0, 1, -1, 0];
51+
List<int> dy = [1, 0, 0, -1];
52+
53+
int dijkstra(List<List<int>> heights) {
54+
int rows = heights.length;
55+
int cols = heights[0].length;
56+
57+
List<List<int>> pq = List.generate(rows, (_) => List<int>.filled(cols, 0));
58+
for (int i = 0; i < rows; i++) {
59+
for (int j = 0; j < cols; j++) {
60+
pq[i][j] = i * cols + j;
61+
effort[i][j] = 1000;
62+
}
63+
}
64+
65+
effort[0][0] = 0;
66+
pq[0][0] = 0;
67+
68+
while (true) {
69+
int minEffort = 1000;
70+
int minEffortX = -1;
71+
int minEffortY = -1;
72+
73+
for (int i = 0; i < rows; i++) {
74+
for (int j = 0; j < cols; j++) {
75+
if (effort[i][j] < minEffort) {
76+
minEffort = effort[i][j];
77+
minEffortX = i;
78+
minEffortY = j;
79+
}
80+
}
81+
}
82+
83+
if (minEffortX == rows - 1 && minEffortY == cols - 1) {
84+
return minEffort;
85+
}
86+
87+
for (int i = 0; i < 4; i++) {
88+
int newX = minEffortX + dx[i];
89+
int newY = minEffortY + dy[i];
90+
91+
if (newX >= 0 && newX < rows && newY >= 0 && newY < cols) {
92+
int newEffort = max(effort[minEffortX][minEffortY],
93+
(heights[minEffortX][minEffortY] - heights[newX][newY]).abs());
94+
95+
if (newEffort < effort[newX][newY]) {
96+
effort[newX][newY] = newEffort;
97+
}
98+
}
99+
}
100+
101+
// Mark this cell as visited by setting its effort to a very large value
102+
effort[minEffortX][minEffortY] = 1000;
103+
}
104+
}
105+
106+
int minimumEffortPath(List<List<int>> heights) {
107+
return dijkstra(heights);
108+
}
109+
}
110+
111+
class Solution {
112+
late List<List<bool>> visited;
113+
final directionsX = [0, 1, -1, 0];
114+
final directionsY = [1, 0, 0, -1];
115+
late int numRows, numCols;
116+
117+
void dfs(int x, int y, int limitEffort, List<List<int>> heights) {
118+
if (visited[x][y]) return;
119+
visited[x][y] = true;
120+
121+
if (x == numRows - 1 && y == numCols - 1) return;
122+
123+
for (int i = 0; i < 4; i++) {
124+
int newX = x + directionsX[i];
125+
int newY = y + directionsY[i];
126+
127+
if (newX < 0 || newX >= numRows || newY < 0 || newY >= numCols) continue;
128+
129+
int newEffort = (heights[x][y] - heights[newX][newY]).abs();
130+
if (newEffort <= limitEffort) {
131+
dfs(newX, newY, limitEffort, heights);
132+
}
133+
}
134+
}
135+
136+
int minimumEffortPath(List<List<int>> heights) {
137+
numRows = heights.length;
138+
numCols = heights[0].length;
139+
140+
visited = List.generate(numRows, (i) => List<bool>.filled(numCols, false));
141+
142+
int lowerLimit = 0;
143+
int upperLimit = 1000000;
144+
145+
while (lowerLimit < upperLimit) {
146+
int mid = (upperLimit + lowerLimit) ~/ 2;
147+
for (var row in visited) {
148+
row.fillRange(0, numCols, false);
149+
}
150+
151+
dfs(0, 0, mid, heights);
152+
153+
if (visited[numRows - 1][numCols - 1]) {
154+
upperLimit = mid;
155+
} else {
156+
lowerLimit = mid + 1;
157+
}
158+
}
159+
160+
return lowerLimit;
161+
}
162+
}
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package main
2+
3+
import (
4+
"container/heap"
5+
)
6+
7+
// Create a struct to represent a cell's coordinates and effort
8+
type Cell struct {
9+
x int
10+
y int
11+
effort int
12+
}
13+
14+
// Define changes in x and y coordinates for each direction
15+
16+
var (
17+
dy = [4]int{1, 0, 0, -1}
18+
dx = [4]int{0, 1, -1, 0}
19+
)
20+
21+
// Function to find the minimum effort path
22+
func minimumEffortPath(heights [][]int) int {
23+
rows, cols := len(heights), len(heights[0])
24+
25+
// Create a 2D slice to store effort for each cell
26+
effort := make([][]int, rows)
27+
for i := range effort {
28+
effort[i] = make([]int, cols)
29+
}
30+
31+
// Initialize effort for each cell to maximum value
32+
for i := 0; i < rows; i++ {
33+
for j := 0; j < cols; j++ {
34+
effort[i][j] = 1 << 31 // Initialize with maximum int value
35+
}
36+
}
37+
38+
// Priority queue to store {effort, {x, y}}
39+
pq := make(PriorityQueue, 0)
40+
heap.Init(&pq)
41+
pq.Push(&Cell{0, 0, 0}) // Start from the top-left cell
42+
effort[0][0] = 0 // Initial effort at the starting cell
43+
44+
for pq.Len() > 0 {
45+
current := heap.Pop(&pq).(*Cell)
46+
cost := current.effort
47+
48+
x, y := current.x, current.y
49+
50+
// Skip if we've already found a better effort for this cell
51+
if cost > effort[x][y] {
52+
continue
53+
}
54+
55+
// Stop if we've reached the bottom-right cell
56+
if x == rows-1 && y == cols-1 {
57+
return cost
58+
}
59+
60+
// Explore each direction (up, down, left, right)
61+
for i := 0; i < 4; i++ {
62+
newX, newY := x+dx[i], y+dy[i]
63+
64+
// Check if the new coordinates are within bounds
65+
if newX < 0 || newX >= rows || newY < 0 || newY >= cols {
66+
continue
67+
}
68+
69+
// Calculate new effort for the neighboring cell
70+
newEffort := max(effort[x][y], abs(heights[x][y]-heights[newX][newY]))
71+
72+
// Update effort if a lower effort is found for the neighboring cell
73+
if newEffort < effort[newX][newY] {
74+
effort[newX][newY] = newEffort
75+
heap.Push(&pq, &Cell{newX, newY, newEffort})
76+
}
77+
}
78+
}
79+
return effort[rows-1][cols-1] // Minimum effort for the path to the bottom-right cell
80+
}
81+
82+
// PriorityQueue is a priority queue of *Cell.
83+
type PriorityQueue []*Cell
84+
85+
func (pq PriorityQueue) Len() int { return len(pq) }
86+
func (pq PriorityQueue) Less(i, j int) bool { return pq[i].effort < pq[j].effort }
87+
func (pq PriorityQueue) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] }
88+
89+
func (pq *PriorityQueue) Push(x interface{}) {
90+
item := x.(*Cell)
91+
*pq = append(*pq, item)
92+
}
93+
94+
func (pq *PriorityQueue) Pop() interface{} {
95+
old := *pq
96+
n := len(old)
97+
item := old[n-1]
98+
*pq = old[0 : n-1]
99+
return item
100+
}
101+
102+
// Helper function to find the maximum of two integers
103+
func max(a, b int) int {
104+
if a > b {
105+
return a
106+
}
107+
return b
108+
}
109+
110+
// Helper function to find the absolute value of an integer
111+
func abs(x int) int {
112+
if x < 0 {
113+
return -x
114+
}
115+
return x
116+
}
117+
/*
118+
119+
120+
121+
// Create a struct to represent coordinates
122+
type Coordinate struct {
123+
x, y int
124+
}
125+
126+
// Define changes in x and y coordinates for each direction
127+
var directionsX = [4]int{0, 1, -1, 0}
128+
var directionsY = [4]int{1, 0, 0, -1}
129+
130+
// Function to perform depth-first search (DFS)
131+
func dfs(x, y, limitEffort int, heights [][]int, visited [][]bool) {
132+
if visited[x][y] {
133+
return
134+
}
135+
visited[x][y] = true
136+
137+
// Stop if we've reached the bottom-right cell
138+
if x == len(heights)-1 && y == len(heights[0])-1 {
139+
return
140+
}
141+
142+
// Explore each direction (up, down, left, right)
143+
for i := 0; i < 4; i++ {
144+
newX, newY := x+directionsX[i], y+directionsY[i]
145+
146+
// Check if the new coordinates are within bounds
147+
if newX < 0 || newX >= len(heights) || newY < 0 || newY >= len(heights[0]) {
148+
continue
149+
}
150+
151+
// Go to the next cell if the effort is within the limit
152+
newEffort := abs(heights[x][y] - heights[newX][newY])
153+
if newEffort <= limitEffort {
154+
dfs(newX, newY, limitEffort, heights, visited)
155+
}
156+
}
157+
}
158+
159+
// Function to find the minimum effort path
160+
func minimumEffortPath(heights [][]int) int {
161+
numRows, numCols := len(heights), len(heights[0])
162+
163+
// Initialize visited array
164+
visited := make([][]bool, numRows)
165+
for i := range visited {
166+
visited[i] = make([]bool, numCols)
167+
}
168+
169+
// Bound for our binary search
170+
lowerLimit, upperLimit := 0, 1_000_000
171+
172+
for lowerLimit < upperLimit {
173+
mid := (upperLimit + lowerLimit) / 2
174+
for _, row := range visited {
175+
for j := range row {
176+
row[j] = false
177+
}
178+
}
179+
180+
dfs(0, 0, mid, heights, visited)
181+
182+
if visited[numRows-1][numCols-1] {
183+
upperLimit = mid
184+
} else {
185+
lowerLimit = mid + 1
186+
}
187+
}
188+
189+
return lowerLimit
190+
}
191+
192+
// Helper function to find the absolute value of an integer
193+
func abs(x int) int {
194+
if x < 0 {
195+
return -x
196+
}
197+
return x
198+
}
199+
Pt
200+
201+
*/

0 commit comments

Comments
 (0)