题目LCR 115. 序列重建

题目LCR 115. 序列重建

给定一个整数数组 nums,其中 nums 是一个长度为 n 的排列,还提供了一个二维数组 sequences,每个 sequences[i] 都是 nums 的子序列。要求判断 nums 是否是唯一的最短超序列。

最短超序列是一个长度最短且包含所有 sequences[i] 子序列的序列。要判断 nums 是否为唯一的最短超序列,必须确保没有其他序列能与 nums 不同但依然满足所有 sequences[i] 子序列的要求。

解题思路

核心思路:由于题目涉及元素之间的相对顺序关系,这些顺序关系可以通过有向图来表示。只要通过拓扑排序确定有向图的排序是唯一的,并且所有关系都是单向确定的,那么超序列的可能性也是唯一的。
这道题的核心在于检查 nums 是否是给定的 sequences 的唯一最短超序列。我们可以通过 拓扑排序 来验证唯一性,具体步骤如下:

  1. 构建有向图:从 sequences 中提取元素间的顺序关系,建立有向图,节点是 nums 的元素,边表示元素之间的相对顺序。
  2. 记录入度:统计每个节点的入度(即指向该节点的边的数量)。
  3. 拓扑排序
    • 从入度为 0 的节点开始逐步进行排序。
    • 若每次只能有一个入度为 0 的节点加入排序队列,说明序列是唯一确定的;如果某时刻有多个入度为 0 的节点,说明可能存在多个有效的序列,返回 false
  4. 验证排序结果:若拓扑排序得到的序列与 nums 一致,则说明 nums 是唯一的最短超序列,返回 true;否则返回 false

代码实现

class Solution {
public:
    bool sequenceReconstruction(vector<int>& nums, vector<vector<int>>& sequences) {
        int n = nums.size();
        
        // 构建图和入度表
        vector<vector<int>> graph(n + 1); // n+1 因为节点从 1 开始
        vector<int> inDegree(n + 1, 0);

        // 构建图
        for (const auto& seq : sequences) {
            for (int i = 1; i < seq.size(); ++i) {
                int prev = seq[i - 1], next = seq[i];
                graph[prev].push_back(next);
                inDegree[next]++;
            }
        }

        // 拓扑排序
        queue<int> q;
        // 首先将入度为 0 的节点加入队列
        for (int i = 1; i <= n; ++i) {
            if (inDegree[i] == 0) {
                q.push(i);
            }
        }

        vector<int> topoResult;
        while (!q.empty()) {
            // 如果队列中有多个元素,说明拓扑排序不是唯一的
            if (q.size() > 1) {
                return false;
            }
            
            int node = q.front();
            q.pop();
            topoResult.push_back(node);

            // 遍历该节点的所有邻居,减少其入度
            for (int neighbor : graph[node]) {
                inDegree[neighbor]--;
                // 如果某个邻居的入度为 0,加入队列
                if (inDegree[neighbor] == 0) {
                    q.push(neighbor);
                }
            }
        }

        // 判断拓扑排序的结果是否与 nums 一致
        return topoResult == nums;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值