leetcode
leetcode 2951 ~ 3000
序列重建

序列重建

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 71 ms, 内存: 19.4 MB


import java.util.*;
import java.util.stream.*;

// 思路:我们将使用拓扑排序的方法来检查 nums 是否是唯一的最短超序列。通过构建有向图和计算入度,我们可以确定唯一性。
public class Solution {
    public boolean sequenceReconstruction(int[] nums, List<List<Integer>> sequences) {
        int n = nums.length;
        int[] inDegree = new int[n + 1];
        Map<Integer, List<Integer>> graph = IntStream.rangeClosed(1, n).boxed()
            .collect(Collectors.toMap(i -> i, i -> new ArrayList<>()));
        sequences.forEach(sequence -> IntStream.range(0, sequence.size() - 1).forEach(i -> {
            graph.get(sequence.get(i)).add(sequence.get(i + 1));
            inDegree[sequence.get(i + 1)]++;
        }));
        Queue<Integer> queue = IntStream.rangeClosed(1, n).filter(i -> inDegree[i] == 0).boxed()
            .collect(Collectors.toCollection(LinkedList::new));
        int index = 0;
        while (!queue.isEmpty()) {
            if (queue.size() > 1) return false;
            int current = queue.poll();
            if (nums[index++] != current) return false;
            graph.get(current).forEach(neighbor -> {
                if (--inDegree[neighbor] == 0) queue.add(neighbor);
            });
        }
        return index == n;
    }
}

解释

方法:

这个题解使用了拓扑排序的思路来解决问题。首先,构建一个有向图和每个节点的入度表。遍历给定的序列,对于序列中相邻的元素a和b,将a指向b的边添加到图中,并且b的入度加1。然后,使用一个队列来进行拓扑排序。初始时,将所有入度为0的节点加入队列。在拓扑排序的过程中,每次从队列中取出一个节点,然后遍历其所有相邻的节点,将这些节点的入度减1,如果某个相邻节点的入度变为0,则将其加入队列。如果在任何时刻队列中有多于一个节点,说明存在多个可能的序列,返回false。最后,如果遍历的节点数等于n,则说明给定的序列可以唯一确定一个序列,返回true,否则返回false。

时间复杂度:

O(n + sum(sequences[i].length))

空间复杂度:

O(n + sum(sequences[i].length))

代码细节讲解

🦆
在构建图的过程中,对于序列中相邻的元素a和b,你是如何确保不会重复添加同一条边a到b?
题解中并没有明确说明如何避免重复添加边a到b。在实际实现中,可以通过检查是否已经存在从a到b的边来避免重复添加。这可以通过在构建图时,为每个节点维护一个集合来存储其所有邻接点,并在添加边之前检查目标节点b是否已存在于节点a的邻接集合中。如果不存在,则添加边并更新入度,如果已存在,则忽略。这样可以确保每条边只被添加一次,从而防止重复添加。
🦆
题解中提到,如果在任何时刻队列中有多于一个节点,则存在多个可能的序列并返回false。这种情况是如何影响序列的唯一性的?
在拓扑排序中,队列中同时存在多于一个节点的情况意味着图中存在多个节点同时没有任何入边,即有多个节点可以作为排序的下一个节点。这表明存在多种不同的顺序来进行节点的遍历,从而构造出多种不同的序列。因此,如果目标是确定一个序列是否能唯一地重建原始序列,那么在任何时刻队列中有多于一个入度为0的节点就会使得原始序列不能被唯一确定,因为这表示有多种可能的序列可以符合给定的顺序限制。
🦆
拓扑排序完成后,为什么通过检查遍历的节点数是否等于n就能确定序列的唯一性?
在拓扑排序中,如果所有的节点都被遍历一次且遍历的节点数正好等于n(序列中的元素数量),这意味着整个图是连通的且没有未解决的依赖(即不存在任何剩余的入边)。这种情况下,如果我们能够从一个节点开始,按照一定的顺序访问所有节点而没有任何剩余的入边,就可以确定这样的顺序是符合所有给定的序列限制的。如果节点数小于n,则说明有些节点由于环或其他依赖未被解决而未被访问,这表明序列无法通过给定的依赖关系唯一确定。

相关问题