leetcode787. K 站中转内最便宜的航班(java)

K 站中转内最便宜的航班

  • leetcode787. K 站中转内最便宜的航班
    • 题目描述
    • 暴力递归
    • 代码演示
    • 递归加缓存
  • 动态规划专题

leetcode787. K 站中转内最便宜的航班

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/cheapest-flights-within-k-stops

题目描述

有 n 个城市通过一些航班连接。给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 pricei 抵达 toi。
现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到出一条最多经过 k 站中转的路线,使得从 src 到 dst 的 价格最便宜 ,并返回该价格。 如果不存在这样的路线,则输出 -1。

暴力递归

如果用递归来解的话.这题就类似于最小路径和问题,同样的套路也可以用在这个问题上,如图演示:
leetcode787. K 站中转内最便宜的航班(java)_第1张图片
s1, s2 是指向 dst 的相邻节点,它们之间的权重我是知道的,分别是 w1, w2。
只要我知道了从 src 到 s1, s2 的最短路径,我不就知道 src 到 dst 的最短路径了吗!

这样就可以看出递归关系了:
minPath(src, dst) = min(
minPath(src, s1) + w1,
minPath(src, s2) + w2
)

我们要对原始数组做下处理,记录下可以到某个节点的所有所有线路和权重值,类似图算法的入度出度:

代码演示

    HashMap<Integer, List<int[]>> graphMap;
    //起始位置
    int src;

    /**
     * 
     * @param n 城市数量
     * @param flights 权重数组
     * @param src 起始位置
     * @param dst 终点位置
     * @param K 要经过k个节点
     * @return
     */
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        //边的条数 +1
        this.src = src;
        //要经过K 个节点的话,经过的线路就是K + 1
        K++;
        graphMap = new HashMap<>();
        //记录所有能达到下一个节点的信息
        for (int[] f : flights){
            int from = f[0];
            int to = f[1];
            int price = f[2];
            graphMap.putIfAbsent(to,new LinkedList<int[]>());
            graphMap.get(to).add(new int[]{from,price});
        }
        return process(dst,K);
    }

    /**
     *
     * @param K 需要经过的边数
     * @param dst 目标
     * @return
     */
    public int process(int dst, int K){
        //base case 到达
        if (dst == src){
            return 0;
        }
        //没有机会了 返回 -1
        if(K == 0){
            return -1;
        }
        int res = Integer.MAX_VALUE;
        if(graphMap.containsKey(dst)){
            for (int[] load : graphMap.get(dst)){
                int from = load[0];
                int price = load[1];
                //往前去递归
                int sumMoney = process(from,K - 1);
                if (sumMoney != -1){
                    //记录最小值
                    res = Math.min(res,sumMoney + price);
                }
            }
        }
        return  res == Integer.MAX_VALUE ? -1 : res;
    }

递归加缓存

消除重复计算的问题

    //记录能到达某个节点的所有节点和权重值
    HashMap<Integer, List<int[]>> graphMap;
    //起始位置
    int src;
    /**
     *
     * @param n 城市数量
     * @param flights 权重数组
     * @param src 起始位置
     * @param dst 终点位置
     * @param K 要经过k个节点
     * @return
     */
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        //边的条数 +1
        this.src = src;
        K++;
        graphMap = new HashMap<>();
        for (int[] f : flights){
            int from = f[0];
            int to = f[1];
            int price = f[2];
            graphMap.putIfAbsent(to,new LinkedList<int[]>());
            graphMap.get(to).add(new int[]{from,price});
        }
        //缓存表
        int[][]dp = new int[n][K + 1];
        return process(dst,K,dp);
    }

    /**
     *
     * @param K 需要经过的边数
     * @param dst 目标
     * @return
     */
    public int process(int dst, int K,int[][]dp){
        if (dst == src){
            return 0;
        }
        if(K == 0){
            return -1;
        }
        //表里有数据直接拿
        if(dp[dst][K] != 0){
            return dp[dst][K];
        }
        int res = Integer.MAX_VALUE;
        if(graphMap.containsKey(dst)){
            for (int[] load : graphMap.get(dst)){
                int from = load[0];
                int price = load[1];
                int sumMoney = process(from,K - 1,dp);
                if (sumMoney != -1){
                    res = Math.min(res,sumMoney + price);
                }
            }
        }
        res = res == Integer.MAX_VALUE ? -1 : res;
        //放进缓存表中
        dp[dst][K] = res;
        return  res;
    }

动态规划专题

leetcode63. 不同路径 II

leetcode62. 不同路径

leetcode877. 石子游戏

leetcode64. 最小路径和

leetcode416. 分割等和子集

leetcode354. 俄罗斯套娃信封问题

leetcode300. 最长递增子序列

你可能感兴趣的:(算法,数据结构,java,java,开发语言,leetcode,算法,动态规划)