序列重建
难度:
标签:
题目描述
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?
▷🦆
题解中提到,如果在任何时刻队列中有多于一个节点,则存在多个可能的序列并返回false。这种情况是如何影响序列的唯一性的?
▷🦆
拓扑排序完成后,为什么通过检查遍历的节点数是否等于n就能确定序列的唯一性?
▷