一刷309-剑指 Offer II 115. 重建序列m(444序列重建plus)

题目:
请判断原始的序列 org 是否可以从序列集 seqs 中唯一地 重建 。

序列 org 是 1 到 n 整数的排列,其中 1 ≤ n ≤ 104。重建 是指在序列集 seqs 中构建最短的公共超序列,
即  seqs 中的任意序列都是该最短序列的子序列。
-------------------------
示例 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
 
提示:
1 <= n <= 104
org 是数字 1 到 n 的一个排列
1 <= segs[i].length <= 105
seqs[i][j]32 位有符号整数
---------------------
思考:
根据序列集seqs中每个序列中的元素前后关系建立有向边的整体图关系,
根据拓扑排序出队序列确定是否跟原始序列org元素顺序相同。
----------------------
class Solution {
    public boolean sequenceReconstruction(int[] org, List<List<Integer>> seqs) {
        Set<Integer> set = new HashSet<>();//set查看序列集合中的元素是否完整(满足1~n)
        int n = org.length;
        for (List<Integer> seq : seqs) {
            for (int num : seq) set.add(num);
        }
        if (n == 1 && !set.contains(n)) return false;//原始序列只有一个元素且不在序列集中
        if (set.size() != n) return false;//序列集元素不完整
        Map<Integer, Set<Integer>> graph = new HashMap<>();//建元素之间的有向边关系
        int[] in = new int[n + 1];//记录元素的入度
        for (int i = 1; i <= n; i++) graph.put(i, new HashSet<>());
        for (List<Integer> seq : seqs) {
            for (int i = 0; i < seq.size() - 1; i++) {
                if (!graph.get(seq.get(i)).contains(seq.get(i + 1))) {
                    graph.get(seq.get(i)).add(seq.get(i + 1));
                    in[seq.get(i + 1)]++;
                }
            }
        }
        Queue<Integer> queue = new LinkedList<>();//准备拓扑排序,入度为0的元素入队
        for (int i = 1; i <= n; i++) {//注意要想确定唯一序列
            if (in[i] == 0) queue.offer(i);//队列中每次只可能有唯一入度为0的元素
        }
        List<Integer> list = new ArrayList<>();
        if (queue.size() != 1) return false;//入度为0的元素不唯一则无法确定唯一序列
        while (!queue.isEmpty()) {
            if (queue.size() != 1) return false;
            int cur = queue.poll();
            list.add(cur);
            if (graph.get(cur) == null) continue;
            for (int next : graph.get(cur)) {
                in[next]--;
                if (in[next] == 0) queue.offer(next);
            }
        }
        if (list.size() != n) return false;
        for (int i = 0; i < n; i++) {//一一比较出队序列的元素顺序,若和原始不一致,则重建失败
            if (list.get(i) != org[i]) return false;
        }
        return true;//全部元素符合重建成功
    }
}

LC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值