Formatted question description: https://leetcode.ca/all/444.html

444. Sequence Reconstruction

Medium

Description

Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. The org sequence is a permutation of the integers from 1 to n, with 1 ≤ n ≤ 104. Reconstruction means building a shortest common supersequence of the sequences in seqs (i.e., a shortest sequence so that all sequences in seqs are subsequences of it). Determine whether there is only one sequence that can be reconstructed from seqs and it is the org sequence.

Example 1:

Input:

org: [1,2,3], seqs: [[1,2],[1,3]]

Output:

false

Explanation:

[1,2,3] is not the only one sequence that can be reconstructed, because [1,3,2] is also a valid sequence that can be reconstructed.

Example 2:

Input:

org: [1,2,3], seqs: [[1,2]]

Output:

false

Explanation:

The reconstructed sequence can only be [1,2].

Example 3:

Input:

org: [1,2,3], seqs: [[1,2],[1,3],[2,3]]

Output:

true

Explanation:

The sequences [1,2], [1,3], and [2,3] can uniquely reconstruct the original sequence [1,2,3].

Example 4:

Input:

org: [4,1,5,2,6,3], seqs: [[5,2,6,3],[4,1,5,2]]

Output:

true

Solution

If only one sequence can be reconstructed from seqs, then seqs must contain all adjacent subsequences of length 2 in org. It is possible that seqs contains a subsequence that has length greater than 2 and the elements in the subsequence are all adjacent in org. Besides, seqs must contain all the numbers in org but can’t contain any number that is not in org.

Use a map to store each number and its corresponding index in org. Use an array of type boolean to store whether each adjacent subsequence is contained in seqs. Use a set to store the numbers in seqs.

Loop over org to fill in the map. For each sequence in seqs, first check all the numbers in the sequence. If a number is greater than org.length, then the number can’t be in org, so return false. Otherwise, add the number to the set. Then check each pair of adjacent numbers. If two adjacet numbers’ indices in org are adjacent and the former number’s index is less than the latter number’s index, then set the element at the former number’s index in the boolean array to true. If the former number’s index is greater than or equal to the latter number’s index, then there is a conflict, so return false.

After the loop, check the set’s size. If the set’s size is less than org.length, then return false. Then check all the elements in the boolean array. If there is a false, then return false. Otherwise, return true.

• class Solution {
public boolean sequenceReconstruction(int[] org, List<List<Integer>> seqs) {
if (seqs == null)
return org == null;
if (seqs.size() == 0)
return org.length == 0;
Map<Integer, Integer> numIndexMap = new HashMap<Integer, Integer>();
int length = org.length;
for (int i = 0; i < length; i++)
numIndexMap.put(org[i], i);
boolean[] adjacentSequences = new boolean[length - 1];
Set<Integer> set = new HashSet<Integer>();
for (List<Integer> sequence : seqs) {
for (int num : sequence) {
if (num > length)
return false;
else
}
int size = sequence.size();
for (int i = 1; i < size; i++) {
int num1 = sequence.get(i - 1), num2 = sequence.get(i);
int index1 = numIndexMap.getOrDefault(num1, -1);
int index2 = numIndexMap.getOrDefault(num2, -1);
if (index1 < 0 || index2 < 0 || index1 >= index2)
return false;
if (index2 - index1 == 1)
}
}
if (set.size() < length)
return false;
return false;
}
return true;
}
}

• class Solution:
def sequenceReconstruction(
self, nums: List[int], sequences: List[List[int]]
) -> bool:
g = defaultdict(list)
indeg = [0] * len(nums)
for seq in sequences:
for a, b in pairwise(seq):
g[a - 1].append(b - 1)
indeg[b - 1] += 1
q = deque(i for i, v in enumerate(indeg) if v == 0)
while q:
if len(q) > 1:
return False
i = q.popleft()
for j in g[i]:
indeg[j] -= 1
if indeg[j] == 0:
q.append(j)
return True

############

import collections

class Solution(object):
def sequenceReconstruction(self, org, seqs):
"""
:type org: List[int]
:type seqs: List[List[int]]
:rtype: bool
"""
n = len(org)
graph = collections.defaultdict(list)
visited = {}
incomings = collections.defaultdict(int)
nodes = set()
for seq in seqs:
nodes |= set(seq)
if len(seq) > 0:
incomings[seq[0]] += 0
for i in range(0, len(seq) - 1):
start, end = seq[i], seq[i + 1]
graph[start].append(end)
incomings[end] += 1

count = 0
for node in incomings:
if incomings[node] == 0:
count += 1
if count == 2:
return False
order = []
visited = collections.defaultdict(int)
queue = [q for q in incomings if incomings[q] == 0]
while len(queue) == 1:
top = queue.pop()
order.append(top)
for nbr in graph[top]:
incomings[nbr] -= 1
if incomings[nbr] == 0:
queue.append(nbr)
if len(queue) > 1:
return False
if order == org and len(order) == len(nodes):
return True
return False


• class Solution {
public:
bool sequenceReconstruction(vector<int>& nums, vector<vector<int>>& sequences) {
int n = nums.size();
vector<vector<int>> g(n);
vector<int> indeg(n);
for (auto& seq : sequences) {
for (int i = 1; i < seq.size(); ++i) {
int a = seq[i - 1] - 1, b = seq[i] - 1;
g[a].push_back(b);
++indeg[b];
}
}
queue<int> q;
for (int i = 0; i < n; ++i)
if (indeg[i] == 0) q.push(i);
while (!q.empty()) {
if (q.size() > 1) return false;
int i = q.front();
q.pop();
for (int j : g[i])
if (--indeg[j] == 0) q.push(j);
}
return true;
}
};

• func sequenceReconstruction(nums []int, sequences [][]int) bool {
n := len(nums)
g := make([][]int, n)
indeg := make([]int, n)
for _, seq := range sequences {
for i := 1; i < len(seq); i++ {
a, b := seq[i-1]-1, seq[i]-1
g[a] = append(g[a], b)
indeg[b]++
}
}
q := []int{}
for i, v := range indeg {
if v == 0 {
q = append(q, i)
}
}
for len(q) > 0 {
if len(q) > 1 {
return false
}
i := q[0]
q = q[1:]
for _, j := range g[i] {
indeg[j]--
if indeg[j] == 0 {
q = append(q, j)
}
}
}
return true
}