솔루션: 최소한의 노력으로 경로
23805 단어 leetcodealgorithmsjavascript
Leetcode 문제 #1631(중간): 최소 노력의 경로
설명:
당신은 다가오는 하이킹을 준비하는 등산객입니다. 크기가
heights
인 2D 배열인 rows x columns
가 주어집니다. 여기서 heights[row][col]
는 셀(row, col)
의 높이를 나타냅니다. 왼쪽 상단 셀(0, 0)
에 있으며 오른쪽 하단 셀(rows-1, columns-1)
(즉, 인덱스 0)로 이동하려고 합니다. 위, 아래, 왼쪽 또는 오른쪽으로 이동할 수 있으며 최소한의 노력이 필요한 경로를 찾고자 합니다.경로의 노력은 경로의 연속된 두 셀 사이의 높이의 최대 절대 차이입니다.
왼쪽 상단 셀에서 오른쪽 하단 셀로 이동하는 데 필요한 최소 노력을 반환합니다.
예:
예 1:
입력:
높이 = [[1,2,2],[3,8,2],[5,3,5]]
산출:
2
설명:
[1,3,5,3,5]의 경로는 연속 셀에서 최대 절대 차이가 2입니다. 이것은 최대 절대 차이가 3인 [1,2,2,2,5]의 경로보다 낫습니다. .
비주얼:
예 2:
입력:
높이 = [[1,2,3],[3,8,4],[5,3,5]]
산출:
1
설명:
[1,2,3,4,5]의 경로는 연속 셀에서 최대 절대 차이가 1이므로 경로 [1,3,5,3,5]보다 낫습니다.
비주얼:
예 3:
입력:
높이 = [[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]]
산출:
0
설명:
이 경로는 노력이 필요하지 않습니다.
비주얼:
제약:
아이디어:
높이의 셀을 그래프의 노드로 생각하고 셀에서 이웃으로 이동하는 노력을 두 노드를 연결하는 가장자리의 가중치로 생각하면 BFS 접근 방식을 사용할 수 있습니다. 해결책.
가장자리는 가중치가 있는 것으로 간주되어야 하므로 약간 수정된 Dijkstra의 알고리즘을 사용하여 최소한의 노력으로 경로를 찾을 수 있습니다. Dijkstra의 알고리즘에서 평소와 같이 이동 목록을 보관할 최소 힙 저장소를 구현해야 합니다.
Dijkstra의 알고리즘은 기본적으로 표준 그래프 BFS 접근 방식처럼 작동합니다. 단, 다음 노드에 도달하는 속도(또는 이 경우에는 노력이 거의 없음)에 따라 우선 순위를 정합니다. 그렇게 하기 위해 우리는 어떤 노드가 이미 방문했는지(vis) 추적하고 시작점에서 최소한의 누적 노력으로 도달할 수 있는 가능한 노드를 기반으로 다음 노드의 우선 순위를 지정하는 방법을 사용하면 됩니다. .
효율성을 더욱 높이기 위해 각 노드에서 찾은 최선의 노력을 추적하고 더 나쁜 경로가 힙에 입력되지 않도록 방지할 수 있습니다.
구현:
자바스크립트에서는 0 또는 1만 포함하므로 vis에 Uint8Array를 사용할 수 있습니다. 마찬가지로 1에서 1e6까지의 정수만 포함하므로 노력을 위해 Uint32Array를 사용할 수 있습니다.
또한 MinPriorityQueue()가 있는 코드 버전도 포함시켰습니다. 이 코드는 우리를 위해 min-heap 작업을 수행하지만 특수 제작된 min-heap보다 훨씬 덜 효율적입니다.
최소 힙이 포함된 Javascript 코드:
var minimumEffortPath = function(H) {
let y = H.length, x = H[0].length, last = x*y-1,
vis = new Uint8Array(last+1),
effort = new Uint32Array(last+1).fill(1000001),
heap = [,], node = 0, path = 0, i, j, cell
const heapify = (next, k, l) => {
let newEff = Math.max(path, Math.abs(cell - H[k][l]))
if (effort[next] <= newEff) return
effort[next] = newEff
let i = heap.length, par = i >> 1
heap.push([next,newEff])
while (par && heap[par][1] > heap[i][1]) {
[heap[par], heap[i]] = [heap[i], heap[par]]
i = par, par = i >> 1
}
}
const extract = () => {
let min = heap[1], left, right,
i = 1, child = heap[3] && heap[3][1] < heap[2][1] ? 3 : 2
heap[1] = heap.pop()
while (heap[child] && heap[i][1] > heap[child][1]) {
[heap[i], heap[child]] = [heap[child], heap[i]]
i = child, left = i << 1, right = left + 1
child = heap[right] && heap[right][1] < heap[left][1] ? right : left
}
return min
}
while (node !== last) {
i = ~~(node / x), j = node % x, cell = H[i][j]
if (i > 0 && !vis[node-x]) heapify(node-x, i-1, j)
if (i < y-1 && !vis[node+x]) heapify(node+x, i+1, j)
if (j > 0 && !vis[node-1]) heapify(node-1, i, j-1)
if (j < x-1 && !vis[node+1]) heapify(node+1, i, j+1)
vis[node] = 1
while (vis[node]) [node,path] = extract()
}
return path
};
MinPriorityQueue()가 포함된 자바스크립트 코드:
이 코드는 덜 효율적이지만 읽기 쉽습니다. leetcode가 기본적으로 javascript 구현에서 활성화한 priorityqueue npm 패키지를 사용합니다.
var minimumEffortPath = function(H) {
let y = H.length, x = H[0].length,
vis = new Uint8Array(x*y),
effort = new Uint32Array(x*y).fill(1000001),
node = 0, path = 0, i, j, cell,
pq = new MinPriorityQueue({priority: x => x[1]})
const insert = (next, k, l) => {
let newEff = Math.max(path, Math.abs(cell - H[k][l]))
if (effort[next] <= newEff) return
effort[next] = newEff
pq.enqueue([next, effort[next]])
}
while (node !== x*y-1) {
i = ~~(node / x), j = node % x, cell = H[i][j]
if (i > 0 && !vis[node-x]) insert(node-x, i-1, j)
if (i < y-1 && !vis[node+x]) insert(node+x, i+1, j)
if (j > 0 && !vis[node-1]) insert(node-1, i, j-1)
if (j < x-1 && !vis[node+1]) insert(node+1, i, j+1)
vis[node] = 1
while (vis[node]) [node, path] = pq.dequeue().element
}
return path
};
Reference
이 문제에 관하여(솔루션: 최소한의 노력으로 경로), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/seanpgallivan/solution-path-with-minimum-effort-36jg텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)