LeetCode: Sequence Reconstruction Posted on February 19, 2018July 26, 2020 by braindenny Sequence Reconstruction Similar Problems: CheatSheet: Leetcode For Code Interview CheatSheet: Common Code Problems & Follow-ups Tag: #topologicalsort, #bfs, #manydetails 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. 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 Github: code.dennyzhang.com Credits To: leetcode.com Leave me comments, if you have better ways to solve. Solution // https://code.dennyzhang.com/sequence-reconstruction // Basic Ideas: topological sort // // Build the dependencies, and try to compose the graph // There should be no ambiguous. // // Notice: watch out for invalid input // e.g, seqs: [[1,-9],[-9,-8],[-8,-9]] // Watch out duplicate edges // e.g, seqs: [[1,2],[1,2]] // Watch out: missing seqs: // e.g, org: [1], seqs: [] // // Complexity: Time O(n+e), Space O(n+e) func sequenceReconstruction(org []int, seqs [][]int) bool { indegrees := make([]int, len(org)) for i, _ := range indegrees { indegrees[i] = -1 } edges := map[int]map[int]bool{} for _, seq := range seqs { for _, n := range seq { n-- if n<0 || n>=len(org) { return false } // initialize the node if indegrees[n] == -1 { indegrees[n] = 0 } if _, ok := edges[n]; !ok { edges[n] = map[int]bool{} } } for i:=0; i+1<len(seq); i++ { n1, n2 := seq[i]-1, seq[i+1]-1 // avoid duplicate edges if _, ok := edges[n1][n2]; !ok { // n1->n2 indegrees[n2]++ edges[n1][n2] = true } } } res := []int{} queue := []int{} for i, v := range indegrees { if v == 0 { queue = append(queue, i) res = append(res, i) } } if len(queue) > 1 { return false } for len(queue) > 0 { nexts := []int{} for _, node := range queue { for node2, _ := range edges[node] { indegrees[node2]-- if indegrees[node2] == 0 { nexts = append(nexts, node2) res = append(res, node2) } } } queue = nexts if len(queue) > 1 { return false } } return len(res) == len(org) } // https://code.dennyzhang.com/sequence-reconstruction // Basic Ideas: topological sort + bfs // // Every time, there should be only one node with 0 incoming edges // There should be no circle. All nodes should be reachable // // Notice: there would be duplicate edges // Notice: The default value of 0 for indegrees list might be misleading // // Complexity: Time O(n+e), Space O(n+e) func sequenceReconstruction(org []int, seqs [][]int) bool { if len(org) == 0 { return len(seqs) == 0 } indegrees := make([]int, len(org)) for i, _ := range indegrees { indegrees[i] = -1 } edges := map[int]map[int]bool{} // build edges for _, seq := range seqs { prev := -1 for i:=0; i<len(seq); i++ { cur := seq[i]-1 if cur >= len(org) || cur < 0 { return false } // mark the node as seen if indegrees[cur] == -1 { indegrees[cur] = 0 } if prev != -1 { // mark the edge if _, ok := edges[prev]; !ok { edges[prev] = map[int]bool{} } if _, ok := edges[prev][cur]; !ok { edges[prev][cur] = true indegrees[cur]++ } } prev = cur } } queue := []int{} for i, v := range indegrees { if v == 0 { queue = append(queue, i) } } index := 0 for len(queue) == 1 { // examine the result when we pop node1 := queue[0] if org[index] != node1+1 { return false } index++ indegrees[node1] = -1 // get the nexts l := []int{} for node2, _ := range edges[node1] { indegrees[node2]-- if indegrees[node2] == 0 { l = append(l, node2) } } queue = l } return index == len(org) } Post Views: 3