程序员面试题精选100题(73)-最多转机K次的最便宜航线[算法]

问题:nortant; word-wrap: break-word !important;”>mortant; word-wrap: break-word !important;”>uortant; word-wrap: break-word !important;”>vortant; word-wrap: break-word !important;”>wortant; word-wrap: break-word !important;”>srcortant; word-wrap: break-word !important;”>dstortant; word-wrap: break-word !important;”>srcortant; word-wrap: break-word !important;”>dstortant; word-wrap: break-word !important;”>Kortant; word-wrap: break-word !important;”>srcortant; word-wrap: break-word !important;”>dstortant; word-wrap: break-word !important;”>-1ortant; word-wrap: break-word !important;”>

ortant; word-wrap: break-word !important; font-size: 16px;”>例如:如果n=3,flights = [[0,1,100],[1,2,100],[0,2,500]],那么这3个城市之间的航班可以用下图表示:

《程序员面试题精选100题(73)-最多转机K次的最便宜航线[算法]》

ortant; word-wrap: break-word !important; font-size: 16px;”>如果src=0,dst=2,也就是从城市0出发飞往城市2,当K=0时(中间不能转机),那么最便宜的票价是500;当K=1时(中间最多转机1次),那么最便宜的票价是200(从城市0经过城市1转机到达城市2)。

ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>

ortant; word-wrap: break-word !important; color: rgb(0, 213, 255);”>解法一:深度优先搜索

ortant; word-wrap: break-word !important;”> 

ortant; word-wrap: break-word !important; font-size: 16px;”>首先,我们可以ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important; font-size: 16px; color: rgb(0, 213, 255);”>再考虑中间转机的次数ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>利用票价来为回溯法剪枝。

ortant; word-wrap: break-word !important; font-size: 16px;”> 

ortant; word-wrap: break-word !important; font-size: 16px;”>以下是上述思路的参考代码:

           
            public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
    int[][] graph = new int[n][n];
    for (int[] flight : flights) {
        graph[flight[0]][flight[1]] = flight[2];
    }
   
    boolean[] visited = new boolean[n];
    int[] minCost = {Integer.MAX_VALUE};
    findCheapestPrice(graph, visited, src, dst, K, minCost, 0);
   
    return minCost[0] == Integer.MAX_VALUE ? -1 : minCost[0];
}

private void findCheapestPrice(int[][] graph, boolean[] visited,
                               int src, int dst, int K, int[] minCost, int cost) {
    if (src == dst) {
        minCost[0] = Math.min(minCost[0], cost);
    }
   
    if (K >= 0 && cost < minCost[0]) {
        for (int i = 0; i < graph.length; ++i) {
            if (graph[src][i] != 0 && !visited[i]) {
                visited[i] = true;
                findCheapestPrice(graph, visited, i, dst, K - 1,
                                  minCost, cost + graph[src][i]);
                visited[i] = false;
            }
        }
    }
}

ortant; word-wrap: break-word !important; color: rgb(0, 213, 255);”>解ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>最短路径。这个题目不是求从src到dst的最短路径,而是票价最便宜的线路,因此要对常规的广度优先搜索算法稍微做点ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important; font-size: 16px;”> 

ortant; word-wrap: break-word !important; font-size: 16px;”>

基于广度优先搜索算法的参考代码如下:

public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
    int[][] graph = new int[n][n];
    for (int[] flight : flights) {
        graph[flight[0]][flight[1]] = flight[2];
    }
   
    int[] costs = new int[n];
    Arrays.fill(costs, Integer.MAX_VALUE);
   
    Set<Integer> set1 = new HashSet<>();
    set1.add(src);
    costs[src] = 0;
   
    while (!set1.isEmpty() && K >= 0) {
        Set<Integer> set2 = new HashSet<>();
        for (int from : set1) {
            for (int i = 0; i < n; ++i) {
                if (graph[from][i] > 0 && costs[from] + graph[from][i] < costs[i]) {
                    costs[i] = costs[from] + graph[from][i];
                    set2.add(i);
                }
            }
        }
       
        set1 = set2;
        K--;
    }
   
    return costs[dst] == Integer.MAX_VALUE ? -1 : costs[dst];
}


上述代码中数组costs的意义是经过若干步骤之后从src出发到达每个城市的最低票价。

ortant; word-wrap: break-word !important; font-size: 16px;”>ortant; word-wrap: break-word !important; color: rgb(0, 213, 255);”>法三:动态规划

ortant; word-wrap: break-word !important; font-size: 16px;”>由于问题是求最低票价,也就是ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important; font-size: 16px;”> 

ortant; word-wrap: break-word !important; font-size: 16px;”>

ortant; word-wrap: break-word !important; font-size: 16px;”>该思路的参考代码如下:

public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
    int[][] dp = new int[2][n];
    for (int[] row : dp) {
        Arrays.fill(row, Integer.MAX_VALUE);
    }
   
    dp[0][src] = 0;
    int cur = 1;
    while (K >= 0) {
        int prev = 1 - cur;
        for (int[] flight : flights) {
            if (dp[prev][flight[0]] < Integer.MAX_VALUE) {
                dp[cur][flight[1]] = Math.min(dp[cur][flight[1]],
                                              dp[prev][flight[0]] + flight[2]);
            }
        }
       
        dp[prev] = Arrays.copyOf(dp[cur], n);
        cur = prev;
        K--;
    }
   
    return dp[1 - cur][dst] == Integer.MAX_VALUE ? -1 : dp[1 - cur][dst];
}   

ortant; word-wrap: break-word !important; font-size: 16px;”>

ortant; word-wrap: break-word !important; font-size: 16px;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>ortant; word-wrap: break-word !important;”>本文转载自微信公众号青云算法扫描下面的二维码,关注“青云算法”微信公众号,学习更多高频算法面试题的解法。

《程序员面试题精选100题(73)-最多转机K次的最便宜航线[算法]》

    原文作者:程序员面试题精选
    原文地址: http://zhedahht.blog.163.com/blog/static/25411174201821571758125/
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞