【Lintcode】1582. Minimum Path Sum II

题目地址:

https://www.lintcode.com/problem/minimum-path-sum-ii/description

给定一个二维矩阵 A A A,求从左下角到右上角的所有路径中权值和最小的路径,返回那个最小的权值和。每一步允许走四周的四个方向。权值和定义为路径上所有数字之和。

思路是Dijkstra算法。这题基本上就是Dijkstra算法的直接应用。下面简要描述二叉堆优化下的Dijkstra算法:
1、开一个class叫Pair,存坐标以及到当前坐标的路径和;
2、开一个最小堆,按照路径和来比较,小者优先,并将起点入堆;
3、堆不空则进行循环,将堆顶出堆,如果其恰好就是终点,则直接返回路径和;否则看一下其是否计算过(这里计算过的意思是到达这个位置的最短路径和有没有被计算过。Dijkstra算法的性质告诉我们,每次出堆的元素就恰好代表了最小路径和),如果计算过则跳过;否则标记其为计算过,并四个方向拓展,将新的未计算过的位置入堆。

代码如下:

import java.util.HashSet;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Set;

public class Solution {
    
    class Pair {
        int x, y, sum;
        
        public Pair(int x, int y, int sum) {
            this.x = x;
            this.y = y;
            this.sum = sum;
        }
    
        @Override
        public boolean equals(Object o) {
            Pair pair = (Pair) o;
            return x == pair.x && y == pair.y;
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }
    
    /**
     * @param matrix: a matrix
     * @return: the minimum height
     */
    public int minPathSumII(int[][] matrix) {
        // Write your code here
        PriorityQueue<Pair> minHeap = new PriorityQueue<>((p1, p2) -> Integer.compare(p1.sum, p2.sum));
        
        int m = matrix.length, n = matrix[0].length;
        minHeap.offer(new Pair(m - 1, 0, matrix[m - 1][0]));
        
        Set<Pair> visited = new HashSet<>();
        int[] d = {1, 0, -1, 0, 1};
        while (!minHeap.isEmpty()) {
            Pair cur = minHeap.poll();
            // 第一次出堆走到终点的路径就是权值和最小的路径,返回权值和
            if (cur.x == 0 && cur.y == n - 1) {
                return cur.sum;
            }
            
    		// visited包含,则说明最小值已经算出来了,略过之
            if (visited.contains(cur)) {
                continue;
            }
            
            // 否则标记为最小值已经算出
            visited.add(cur);
            
            for (int i = 0; i < 4; i++) {
                int nextX = cur.x + d[i], nextY = cur.y + d[i + 1];
                if (inBound(nextX, nextY, matrix)) {
                    Pair next = new Pair(nextX, nextY, cur.sum + matrix[nextX][nextY]);
                    if (!visited.contains(next)) {
                        minHeap.offer(next);
                    }
                }
            }
        }
        
        return -1;
    }
    
    private boolean inBound(int x, int y, int[][] matrix) {
        return 0 <= x && x < matrix.length && 0 <= y && y < matrix[0].length;
    }
}

时间复杂度 O ( E log ⁡ V ) O(E\log V) O(ElogV),空间 O ( V ) O(V) O(V)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值