剑指 Offer II 115. 重建序列(444. 序列重建)

题目:

思路:

【0】首先是读题,看的是玄里玄乎的,但其实本质上就是问sequences是否存在路径能够走完整个nums数组。如nums是【1,2,3】而sequences存在【1,2】和【2,3】,故从1走到2,再从2走到3,实际上便是走完了整个nums数组。

【1】使用边hash比对的方式:

【2】拓扑排序的方式:

代码展示:

拓扑排序的方式:

//时间22 ms击败70.26%
//内存48.8 MB击败62.7%
class Solution {
    public boolean sequenceReconstruction(int[] nums, int[][] sequences) {
        int n = nums.length;
        int[] indegrees = new int[n + 1];
        Set<Integer>[] graph = new Set[n + 1];
        //构建图的结构
        for (int i = 1; i <= n; i++) {
            graph[i] = new HashSet<Integer>();
        }
        //填充图数据,且记录节点的入度数
        for (int[] sequence : sequences) {
            int size = sequence.length;
            for (int i = 1; i < size; i++) {
                int prev = sequence[i - 1], next = sequence[i];
                if (graph[prev].add(next)) {
                    indegrees[next]++;
                }
            }
        }
        Queue<Integer> queue = new ArrayDeque<Integer>();
        //将所有的入度数为0的节点取出
        for (int i = 1; i <= n; i++) {
            if (indegrees[i] == 0) {
                queue.offer(i);
            }
        }
        while (!queue.isEmpty()) {
            // 依据题意有解的话,必然存在一个整条链路,所以入度数为0的只有1,
            // 如果存在其他的必然某一条边是不被纳入的,如【1,2,3,4】,
            // 即只有出现【1,2】,【2,4】,【3,4】这种,1和3入度为0。你要知道如果存在【x,3】那么3的入度必不为0.
            if (queue.size() > 1) {
                return false;
            }
            int num = queue.poll();
            Set<Integer> set = graph[num];
            for (int next : set) {
                indegrees[next]--;
                if (indegrees[next] == 0) {
                    queue.offer(next);
                }
            }
        }
        return true;
    }
}

 

使用边hash比对的方式:

//时间1 ms击败100%
//内存44.1 MB击败90.30%   
// 根据nums中的边构建map,判断nums中的边是否都在sequences中出现
class Solution { public boolean sequenceReconstruction(int[] nums, int[][] sequences) { int n = nums.length; int[] map = new int[n+1]; int count = 0; //由于是要找出nums数组的全部边,那么将其存储下来 for(int i=0;i<n-1;i++){ map[nums[i]] = nums[i+1]; count++; } //通过遍历sequences,判断是否map中的所有边都是存在的 for(int[] sequence:sequences){ for(int i=0;i<sequence.length-1;i++){ if(map[sequence[i]]==sequence[i+1]){ count--; //已经消耗过的边,直接变为-1(这是基于题意,数字在1-n,故变为负数表示消耗),不会重复消耗 map[sequence[i]]=-1; } } } return count==0; } }

 

posted @ 2023-04-23 12:11  忧愁的chafry  阅读(15)  评论(0编辑  收藏  举报