​LeetCode刷题实战444:序列重建

程序IT圈

共 1750字,需浏览 4分钟

 ·

2021-11-26 19:47

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 序列重建,我们先来看题面:
https://leetcode-cn.com/problems/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.


验证原始的序列 org 是否可以从序列集 seqs 中唯一地重建。
序列 org 是 1 到 n 整数的排列,其中 1 ≤ n ≤ 104。
重建是指在序列集 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


解题

https://blog.csdn.net/weixin_44171872/article/details/108865453

主要思路:
(1)先判断给出的序列集中包含的所有元素,是否是1到 n的所有的元素;
(2)根据给出的序列集,建立出度的有向图,并统计各个点的入度;
(3)在建好的图中,进行拓扑排序,且保证只能建立一种顺序,则排序的过程中,要保证每次排序时,起始的结点,既入度为0的点只有一个(这个使用队列的大小进行判断);
(4)对排好的序列,进行判断,既首先大小要和给出的数组相同,其次,各个元素要相同;

class Solution {
public:
    bool sequenceReconstruction(vector<int>& org, vector<vector<int>>& seqs) {
        int n=org.size();
        //统计序列集中的各个元素,保证所有的元素是唯一的1到n的数字
        vector<bool> signs(n+1,false);
        for(vector<int>& vec:seqs){//统计
            for(int&num:vec){
                if(num>n||num<=0){//保证不越界
                    return false;
                }
                signs[num]=true;
            }
        }
        for(int i=1;i<=n;++i){//判断元素的是否符合要求
            if(!signs[i]){
                return false;
            }
        }
        //建有向出度图和统计入度
        vector<vector<int>> graph(n+1);
        vector<int> indegree(n+1,0);
        for(vector<int>& vec:seqs){
            for(int i=0;i-1;++i){
                graph[vec[i]].push_back(vec[i+1]);
                ++indegree[vec[i+1]];
            }
        }
        //找出起始的结点
        queue<int> q;
        for(int i=1;i<=n;++i){
            if(indegree[i]==0){
                q.push(i);
            }
        }
        vector<int> res;//存储排序后的序列
        while(!q.empty()){
            if(q.size()>1){//保证只有一种序列
                return false;
            }
            //取出当前结点
            int cur=q.front();
            q.pop();
            res.push_back(cur);
            //更新相关的入读图
            for(int& num:graph[cur]){
                --indegree[num];
                if(indegree[num]==0){//统计新的起始点
                    q.push(num);
                }
            }
        }
        //先判断大小
        if(res.size()!=n){
            return false;
        }
        //再判断一致性
        return res==org;
    }
};


好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。

上期推文:

LeetCode1-440题汇总,希望对你有点帮助!

LeetCode刷题实战441:排列硬币

LeetCode刷题实战442:数组中重复的数据

LeetCode刷题实战443:压缩字符串


浏览 26
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报