[LeetCode]Sequence Reconstruction

题目描述:

LeetCode 444. Sequence Reconstruction

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

题目大意:

判断原始序列org能否由一组序列seqs重建。org序列是整数1到n的一个排列,其中1 ≤ n ≤ 10^4。重建意味着使用seqs中的序列构建一个最短公共超序列(也就是说,一个最短的序列满足seqs中的所有序列均为其子序列)。判断seqs中的序列能否唯一确定org序列。

解题思路:

解法I 拓扑排序(Topological Sort)

将seqs中的各序列seq按照其中元素出现的先后顺序建立有向图g。

例如seqs中的某序列seq = [1, 2, 3],对应有向图,顶点为1, 2, 3;边为(1, 2), (2, 3)。

利用数组indeg记录各顶点的入度(indegree),sucset记录各顶点的后继(边)。

然后对图g执行拓扑排序,将得到的排序结果与原始序列org作比对即可。

Python代码:

class Solution(object):
    def sequenceReconstruction(self, org, seqs):
        """
        :type org: List[int]
        :type seqs: List[List[int]]
        :rtype: bool
        """
        size = len(org)
        indeg = [0] * size
        sucset = [set() for x in range(size)]
        if not seqs: return False
        for seq in seqs:
            if any(s > size or s < 1 for s in seq):
                return False
            for i in range(1, len(seq)):
                if seq[i] not in sucset[seq[i - 1] - 1]:
                    indeg[seq[i] - 1] += 1
                    sucset[seq[i - 1] - 1].add(seq[i])

        q = [i for i in org if not indeg[i - 1]]
        for x in range(size):
            if len(q) != 1 or q[0] != org[x]:
                return False
            nq = []
            for suc in sucset[q[0] - 1]:
                indeg[suc - 1] -= 1
                if not indeg[suc - 1]:
                    nq.append(suc)
            q = nq
        return True

解法II “边检查法”

首先建立原始序列org中各元素到其下标的映射indexes。

遍历seqs,记当前序列为seq,遍历seq;

记seq中相邻元素为pre, cur,若indexes[pre] > indexes[cur],说明与org中各元素的前后关系产生矛盾,返回False

否则,将(pre, cur)加入边集edges。

最后遍历org,判断其中两两相邻元素构成的边是否都在edges中,若是返回True,否则返回False。

Python代码:

class Solution(object):
    def sequenceReconstruction(self, org, seqs):
        """
        :type org: List[int]
        :type seqs: List[List[int]]
        :rtype: bool
        """
        indexes = {e : i for i, e in enumerate(org)}
        edges = set()

        if not seqs: return False
        for seq in seqs:
            for s in seq:
                if s not in indexes:
                    return False
            for i in range(1, len(seq)):
                pre, cur = seq[i - 1], seq[i]
                if indexes[pre] > indexes[cur]:
                    return False
                edges.add((pre, cur))

        for x in range(1, len(org)):
            if (org[x - 1], org[x]) not in edges:
                return False
        return True

 

本文链接:http://bookshadow.com/weblog/2016/10/30/leetcode-sequence-reconstruction/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。

如果您喜欢这篇博文,欢迎您捐赠书影博客: ,查看支付宝二维码