新增道路查询后的最短距离问题两种情况的处理(JAVA版本)

I

这题的一个主要问题在于可能会出现相交的路径,比如新增一条【0,3】的路径,后续又出现一条【1,4】的路径,这两条路径就会出现一个相交

解题思路:对每个节点进行BFS,用一个list数组储存每个节点可能出现的下一个节点(因为有多条路径所以有多个下一节点),然后对每个下一节点进行重复的循环查询,指导查询到的节点为n-1说明查询到最后一个节点的路径,这时候经过的路径长度就是当前的最短路径长度,

注:进行BFS可以用一个队列存储节点,同时每次用queue的size来表示当前层的循环,当size减小到0的时候重新更新size(类似于树的层序遍历),然后就可以从路径长度1——n-1的方式逐层查询,直到查找到n-1,同时可以用一个visited数组来标记查询过的点,跳过重复的点,因为已经标记过的节点说明之前已经查询过,再重复查询的话对于查询最短路径没有帮助,得到的路径只会大于之前的查询,没有必要

class Solution {
    public int[] shortestDistanceAfterQueries(int n, int[][] queries) {
        //存储第i个节点的下一个节点
        ArrayList<Integer>[] record = new ArrayList[n];
        int[] answer = new int[queries.length];
        int len = n - 1;
        int cnt = 0;

        for (int i = 0; i < n; i++) {
            ArrayList<Integer> list = new ArrayList<>();
            list.add(i+1);
            record[i] = list;
        }

        for (int i = 0; i < queries.length; i++) {
            cnt = 1;
            int u = queries[i][0];
            int v = queries[i][1];
            record[u].add(v);

            //开始对更新后的序列进行BFS
            
            int chileRecord = 0; //用来记录每一层有多少个节点
            int nextLay = 0;  //统计下一层有几个节点
            boolean[] visited = new boolean[n];
            visited[0] = true;

            Deque<Integer> queue = new LinkedList<>();
            for (Integer integer : record[0]) {
                queue.addLast(integer);
                visited[integer] = true;
                chileRecord++;
            }

            //这里更好的处理是在里面再加一个循环,简化掉chilerecord和nextlay,直接用
            //queue.size获取每一层的节点树,然后在当前层遍历完后再更新size,进行下一层
            while (!queue.isEmpty()) {
                int addNum = queue.poll();

                chileRecord--;

                if (addNum == n - 1) {
                    answer[i] = cnt;
                    break;
                }
                
                for (int temp : record[addNum]) {
                    //筛选掉已经查询过的节点
                    if (!visited[temp]) {
                        queue.addLast(temp);
                        visited[temp] = true;
                        nextLay++;
                    }
                }

                if (chileRecord == 0) {
                    cnt++;
                    chileRecord = nextLay;
                    nextLay = 0;
                }

            }

        }
        return answer;
    }
}

II

相比于上一题的区别在于添加了一个通道的约束,从而不会出现两条通道相交的情况,只会出现,一个的终点是另一条通道的起点,或者通道是包含的关系,所以这个题不能使用上面的BFS的方法,会出现超时

解题思路:建立一个数组record来标记每个节点i能到达的下一节点是什么,如果有一个通道是从i到一个更远的终点d,则更新之前i能到达的终点d‘和d之间的节点的下一节点为0,因为有一个更远的终点能够覆盖这些节点,所以这些通道的路径就省了,将d’到d中间的节点的record设置为0,表示如果这个节点的路径被覆盖了,不需要进行操作

class Solution {
    public int[] shortestDistanceAfterQueries(int n, int[][] queries) {
        //存储第i个节点的下一个节点
        int[] record = new int[n];
        int[] answer = new int[queries.length];
        int len = n - 1;

        for (int i = 0; i < n - 1; i++) {
            record[i] = i + 1;
        }

        for (int i = 0; i < queries.length; i++) {
            int u = queries[i][0];
            int v = queries[i][1];
            
            //大于0保证当前节点是有下一节点的通道,而不是被覆盖了
            if (record[u]>0 && record[u] < v) {
                for (int l = record[u]; l < v;) {
                    len--;
                    int temp = record[l];
                    record[l] = 0;
                    l = temp;
                }
                record[u] = v;
            }
            answer[i] = len;

        }
        return answer;
    }
}

为什么要有record[u] > 0

如果没有判定大于0,则会出现下面这种,后续的通道已经被之前的通道覆盖,所以没有讨论的意义

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值