LintCode-605 Sequence Reconstruction 序列重构

描述

判断是否序列 org 能唯一地由 seqs重构得出.
org是一个由从1到n的正整数排列而成的序列,1 ≤ n ≤ 10^4。
重构表示组合成seqs的一个最短的父序列 (意思是,一个最短的序列使得所有 seqs里的序列都是它的子序列).
判断是否有且仅有一个能从 seqs重构出来的序列,并且这个序列是org。

样例

例1:

输入:org = [1,2,3], seqs = [[1,2],[1,3]]
输出: false
解释:
[1,2,3] 并不是唯一可以被重构出的序列,还可以重构出 [1,3,2]

例2:

输入: org = [1,2,3], seqs = [[1,2]]
输出: false
解释:
能重构出的序列只有 [1,2].

例3:

输入: org = [1,2,3], seqs = [[1,2],[1,3],[2,3]]
输出: true
解释:
序列 [1,2], [1,3], 和 [2,3] 可以唯一重构出 [1,2,3].

例4:

输入:org = [4,1,5,2,6,3], seqs = [[5,2,6,3],[4,1,5,2]]
输出:true

分析

从题可得,seqs中的序列能且仅能重构出一个org,并且org不能有冗余元素。
涉及到序列的顺序结构,可以考虑从元素的入度着手。

算法
  • 基于seqs,生成拓扑图graph
  • 基于拓扑图,生成入度表indegrees
  • 把入度为0的元素放入列表queue
  • 循环直到queue为空
    • 取出queue元素
    • 更新入度表
    • 把入度为0的元素放入列表queue
  • 判断返回的列表topo_order与org是否相同
实现
class Solution:
    """
    @param org: a permutation of the integers from 1 to n
    @param seqs: a list of sequences
    @return: true if it can be reconstructed only one or false
    """
    def sequenceReconstruction(self, org, seqs):
        # write your code here
        graph = self.build_graph(seqs)
        topo_order = self.topological_sort(graph)
        return topo_order == org

    def build_graph(self, seqs):
        # graph保存每个node后面紧跟的neighbor,用于生成入度表
        # e.g.
        # seq1=[1, 2, 3], graph[1]=[2, ], graph[2]=[3, ], graph[3]=[]
        # seq2=[1, 3, 4], graph[1]=[2, 3], graph[2]=[3, ], graph[3]=[4, ], graph[4]=[]
        graph = {}
        for seq in seqs:
            for idx, node in enumerate(seq):
                if node not in graph:
                    graph[node] = set()
                if idx < len(seq) - 1:  # 防止idx + 1越界
                    graph[node].add(seq[idx + 1])
        return graph
        
    def get_indegrees(self, graph):
        # indegrees = {0: 0, 1: 0, 2: 0, ..., n: 0}  n是node的种类数,即graph的长度
        # 如上例子:indegrees[1]=0, [2]=1, [3]=2, [4]=1
        # 入度为m,即有m个元素能直达自身
        indegrees = dict(zip([node for node in graph], [0 for _ in graph]))
        for node in graph:
            for neighbor in graph[node]:
                indegrees[neighbor] += 1
        return indegrees
        
    def topological_sort(self, graph):
        indegrees = self.get_indegrees(graph)
        
        queue = []
        # 放入起始node
        for node, indegree in indegrees.items():
            if indegree == 0:
                queue.append(node)
                
        topo_order = []
        while queue:
            if len(queue) > 1:
                return None  # 一个前置元素能抵达不止一个元素,即org不仅有一种排序
                             # 直接pass            
            node = queue.pop(0)
            for neighbor in graph[node]:
                indegrees[neighbor] -= 1
                if indegrees[neighbor] == 0:
                    queue.append(neighbor)
            topo_order.append(node)
        
        return topo_order

学习自文章:https://www.jiuzhang.com/solution/sequence-reconstruction/#tag-highlight-lang-python

我是小白,一起努力。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值