[LeetCode] Sequence Reconstruction 序列重建

简介:

Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. The orgsequence 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,问这些子序列能否唯一的重建出原序列。能唯一重建的意思就是任意两个数字的顺序必须是一致的,不能说在一个子序列中1在4的后面,但是在另一个子序列中1在4的前面,这样就不是唯一的了。还有一点就是,子序列seqs中不能出现其他的数字,就是说必须都是原序列中的数字。那么我们可以用了一个一维数组pos来记录org中每个数字对应的位置,然后用一个flags数字来标记当前数字和其前面一个数字是否和org中的顺序一致,用cnt来标记还需要验证顺序的数字的个数,初始化cnt为n-1,因为n个数字只需要验证n-1对顺序即可,然后我们先遍历一遍org,将每个数字的位置信息存入pos中,然后再遍历子序列中的每一个数字,还是要先判断数字是否越界,然后我们取出当前数字cur,和其前一位置上的数字pre,如果在org中,pre在cur之后,那么直接返回false。否则我们看如果cur的顺序没被验证过,而且pre是在cur的前一个,那么标记cur已验证,且cnt自减1,最后如果cnt为0了,说明所有顺序被成功验证了,参见代码如下:

解法一:

class Solution {
public:
    bool sequenceReconstruction(vector<int>& org, vector<vector<int>>& seqs) {
        if (seqs.empty()) return false;
        int n = org.size(), cnt = n - 1;
        vector<int> pos(n + 1, 0), flags(n + 1, 0);
        bool existed = false;
        for (int i = 0; i < n; ++i) pos[org[i]] = i;
        for (auto& seq : seqs) {
            for (int i = 0; i < seq.size(); ++i) {
                existed = true;
                if (seq[i] <= 0 || seq[i] > n) return false;
                if (i == 0) continue;
                int pre = seq[i - 1], cur = seq[i];
                if (pos[pre] >= pos[cur]) return false;
                if (flags[cur] == 0 && pos[pre] + 1 == pos[cur]) {
                    flags[cur] = 1; --cnt;
                }
            }
        }
        return cnt == 0 && existed;
    }
};

下面这种方法跟上面的方法大同小异,用两个哈希表来代替了上面的数组和变量,其中m为数字和其位置之间的映射,pre为当前数字和其前一个位置的数字在org中的位置之间的映射。跟上面的方法的不同点在于,当遍历到某一个数字的时候,我们看当前数字是否在pre中有映射,如果没有的话,我们建立该映射,注意如果是第一个位置的数字的话,其前面数字设为-1。如果该映射存在的话,我们对比前一位数字在org中的位置和当前的映射值的大小,取其中较大值。最后我们遍历一遍org,看每个数字的映射值是否是前一个数字的位置,如果有不是的返回false,全部验证成功返回true,参见代码如下:

解法二:

class Solution {
public:
    bool sequenceReconstruction(vector<int>& org, vector<vector<int>>& seqs) {
        unordered_map<int, int> m, pre;
        for (int i = 0; i < org.size(); ++i) m[org[i]] = i;
        for (auto& seq : seqs) {
            for (int i = 0; i < seq.size(); ++i) {
                if (!m.count(seq[i])) return false;
                if (i > 0 && m[seq[i - 1]] >= m[seq[i]]) return false;
                if (!pre.count(seq[i])) {
                    pre[seq[i]] = (i > 0) ? m[seq[i - 1]] : -1;
                } else {
                    pre[seq[i]] = max(pre[seq[i]], (i > 0) ? m[seq[i - 1]] : -1);
                }
            }
        }
        for (int i = 0; i < org.size(); ++i) {
            if (pre[org[i]] != i - 1) return false;
        }
        return true;
    }
};

本文转自博客园Grandyang的博客,原文链接:序列重建[LeetCode] Sequence Reconstruction ,如需转载请自行联系原博主。

相关文章
|
存储 SQL 关系型数据库
MySQL 给查询结果增列并自定义列数据
MySQL 给查询结果增列并自定义列数据
1698 2
|
11月前
|
人工智能 运维 应用服务中间件
云产品评测|操作系统智能助手OS Copilot新功能
作为一名全栈开发,我在日常维护阿里云服务器时,由于对Linux不熟悉,常常感到运维困难。最近尝试了阿里云推出的OS Copilot,发现它极大简化了操作。通过简单的命令如`co nginx是否安装`和`co 将nginx设置为开启自启动 -t`,可以轻松完成复杂的任务。使用`-f`参数还能处理复杂任务,例如从Nginx日志中提取最常访问的IP地址。此外,Copilot还支持管道解析,帮助解读文件内容。总体而言,OS Copilot显著提升了我的工作效率和信心,建议进一步增加功能和优化体验。
|
存储 安全 API
ZYNQ-使用SD卡读写文本数据
ZYNQ-使用SD卡读写文本数据
1418 0
ZYNQ-使用SD卡读写文本数据
|
SQL 关系型数据库 MySQL
Mybatis批量更新出现BadSqlGrammarException异常解决
解决mybatis批量更新出现异常解决方案
3657 0
|
5天前
|
搜索推荐 编译器 Linux
一个可用于企业开发及通用跨平台的Makefile文件
一款适用于企业级开发的通用跨平台Makefile,支持C/C++混合编译、多目标输出(可执行文件、静态/动态库)、Release/Debug版本管理。配置简洁,仅需修改带`MF_CONFIGURE_`前缀的变量,支持脚本化配置与子Makefile管理,具备完善日志、错误提示和跨平台兼容性,附详细文档与示例,便于学习与集成。
309 116
|
20天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
7天前
|
数据采集 人工智能 自然语言处理
Meta SAM3开源:让图像分割,听懂你的话
Meta发布并开源SAM 3,首个支持文本或视觉提示的统一图像视频分割模型,可精准分割“红色条纹伞”等开放词汇概念,覆盖400万独特概念,性能达人类水平75%–80%,推动视觉分割新突破。
519 47
Meta SAM3开源:让图像分割,听懂你的话