787. Cheapest Flights Within K Stops . (bfs)

3 篇文章 0 订阅

 787. Cheapest Flights Within K Stops

广度优先搜索,

第一种解法超时:

class Solution {
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        int f[][]=new int[n][n];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                f[i][j]=Integer.MAX_VALUE;
        for(int i=0;i<flights.length;i++)
            f[flights[i][0]][flights[i][1]]=flights[i][2];
        int cost=Integer.MAX_VALUE;
        Queue<Point> queue=new LinkedList<Point>();
        queue.offer(new Point(src,K,0));
        while(queue.size()>0){
            Point temp=queue.poll();
            if(temp.k>=0 && f[temp.src][dst]!=Integer.MAX_VALUE)
                cost=Math.min(cost,temp.cost+f[temp.src][dst]);
            if(temp.k>0)
                for(int i=0; i<n;i++)
                    if(f[temp.src][i]!=Integer.MAX_VALUE)
                        queue.offer(new Point(i,temp.k-1,temp.cost+f[temp.src][i]));
        }
        return cost==Integer.MAX_VALUE?-1:cost;
    }
}
class Point{
    int src;
    int k;
    int cost;
    Point(int src,int k,int cost){
        this.src=src;
        this.k=k;
        this.cost=cost;
    }
}

第二种解法对第一种解法降低时间复杂度,首先是用哈希降低访问元素的时间复杂度;

然后是对while(queue.size()>0)何时退出进行分析,除去不必要的重复计算;

难点:何时退出 while(queue.size()>0),解法二显然遇到最优解便退出了,解法一就有很多不必要计算,再对问题进行分析,我们每次使用的是最小的cost去松弛路径,当遇到dst时说明后面的松弛对其已经没影响,所以当前解就是最优解。

思考:为什么每次使用最小的cost去松弛最终得到的解就是最优解,因为我们有bfs的扩展次数记录,假设一个最优解经过k次松弛后还未得到,那么肯定不符合题目要求,我所疑惑的是k,这里的k不是代表k只有k次松弛,而是说k次广度扩展,至于松弛几次,是未知的。

class Solution {
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        Map<Integer,Map<Integer,Integer>> map=new HashMap();
        for(int i=0;i<flights.length;i++){
            if(map.getOrDefault(flights[i][0],null)==null)
                map.put(flights[i][0],new HashMap<Integer,Integer>());
            map.get(flights[i][0]).put(flights[i][1],flights[i][2]);
        }
        PriorityQueue<Node> queue=new PriorityQueue<Node>(new Comparator<Node>(){
            public int compare(Node node1,Node node2){
                return node1.cost-node2.cost;
            }
        });
        queue.offer(new Node(0,src,K));
        while(queue.size()>0){
            Node temp=queue.poll();
            if(temp.src==dst)
                return temp.cost;
            if(temp.k>=0){
                Map<Integer,Integer> temp1=map.getOrDefault(temp.src,new HashMap<Integer,Integer>());
                for(int key:temp1.keySet())
                    queue.offer(new Node( temp.cost+temp1.get(key) , key ,temp.k-1) );
            }
        }
        return -1;
    }
}
class Node{
    int cost;
    int src;
    int k;
    Node(int cost,int src,int k){
        this.cost=cost;
        this.src=src;
        this.k=k;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值