Given an array arr[] and a 2D array sequences[], determine if arr is the shortest possible and the only supersequence for the given sequences. A supersequence is a sequence that has all sequences[i] as subsequences. The task is to return true if arr is the only shortest supersequence for sequences, or false otherwise.
Example:
Input: arr = {1,2,3}, sequences = {{1,2},{1,3}}
Output: false
Explanation: There are two possible supersequences: {1,2,3} and {1,3,2}.
- The sequence {1,2} is a subsequence of both: {1,2,3} and {1,3,2}.
- The sequence {1,3} is a subsequence of both: {1,2,3} and {1,3,2}.
- As arr is not the only shortest supersequence, the output is false.
Input: arr = {1,2,3}, sequences = {{1,2}}
Output: false
Explanation: The shortest possible supersequence is {1,2}.
- The sequence {1,2} is a subsequence of it: {1,2}.
- Since arr is not the shortest supersequence, we return false.
Approach:
The basic is to get topological sort of sequences nodes, if it is unique and equal to arr, then true, else False. Following is how to implement in details:
In each step of topological sorting, if we have more than one node whose incoming nodes count is zero then the togological ordering will not be unique, hence our supersequence won't be unique. So, return False. At last we check if the topological sort contain all nodes in the in seqs and equal to our generated supersequence.
Steps-by-step approach:
- Build Dependency Graph:
- Create a directed graph where vertices are elements in arr.
- Connect consecutive elements in each sequence with directed edges.
- Calculate Indegree:
- Count incoming edges for each vertex (number of elements that must appear before it). if indegree is greater than 1, return false;
- Topological Sort:
- Use a queue to process vertices with indegree 0.
- While the queue is not empty:
- Dequeue a vertex and add it to the result list.
- Decrease the indegree of its outgoing neighbors.
- Add neighbors with indegree 0 to the queue.
- Check if if indegree is greater than 1, return false;
- Check Uniqueness and Length:
- If result is different from arr or has a different length, return false, otherwise return true;
Below is the implementation of the above approach:
#include <bits/stdc++.h>
using namespace std;
// Function to check if arr is the only shortest
// supersequence for sequences
bool sequenceReconstruction(vector<int>& arr,
vector<vector<int> >& sequences)
{
int n = arr.size();
// Create adjacency list to represent dependencies
// between elements
vector<vector<int> > adj(n + 1);
// Store indegree of each element (number of elements
// that must appear before it)
vector<int> indegree(n + 1);
// Build the dependency graph
for (auto& seq : sequences) {
for (int j = 0; j < seq.size() - 1; j++) {
adj[seq[j]].push_back(seq[j + 1]);
indegree[seq[j + 1]]++;
}
}
// Perform topological sort using a queue
queue<int> q;
vector<int> result;
// Add elements with indegree 0 to the queue (starting
// points)
for (int i = 1; i <= n; i++) {
if (indegree[i] == 0) {
q.push(i);
}
}
// If there are multiple elements with indegree 0, it's
// not the only supersequence
if (q.size() > 1) {
return false;
}
// Process elements in topological order
while (q.size()) {
auto curr = q.front();
result.push_back(curr);
q.pop();
// Update indegree of neighbors and add them to the
// queue if they become ready
for (auto c : adj[curr]) {
indegree[c]--;
if (indegree[c] == 0) {
q.push(c);
}
}
// If there are multiple elements ready at the same
// time, it's not the only supersequence
if (q.size() > 1) {
return false;
}
}
// Check if the resulting sequence is the same as the
// given array and has the same length
return (result == arr);
}
// Driver code
int main()
{
vector<int> arr = { 1, 2, 3 };
vector<vector<int> > sequences = { { 1, 2 }, { 1, 3 } };
bool result = sequenceReconstruction(arr, sequences);
if (result) {
cout << "True" << endl;
}
else {
cout << "False" << endl;
}
return 0;
}
import java.util.*;
public class Main {
// Function to check if arr is the only shortest
// supersequence for sequences
static boolean
sequenceReconstruction(List<Integer> arr,
List<List<Integer> > sequences)
{
int n = arr.size();
// Create adjacency list to represent dependencies
// between elements
List<List<Integer> > adj = new ArrayList<>();
for (int i = 0; i <= n; i++) {
adj.add(new ArrayList<>());
}
// Store indegree of each element (number of
// elements that must appear before it)
int[] indegree = new int[n + 1];
// Build the dependency graph
for (List<Integer> seq : sequences) {
for (int j = 0; j < seq.size() - 1; j++) {
int from = seq.get(j);
int to = seq.get(j + 1);
adj.get(from).add(to);
indegree[to]++;
}
}
// Perform topological sort using a queue
Queue<Integer> q = new LinkedList<>();
List<Integer> result = new ArrayList<>();
// Add elements with indegree 0 to the queue
// (starting points)
for (int i = 1; i <= n; i++) {
if (indegree[i] == 0) {
q.add(i);
}
}
// If there are multiple elements with indegree 0,
// it's not the only supersequence
if (q.size() > 1) {
return false;
}
// Process elements in topological order
while (!q.isEmpty()) {
int curr = q.poll();
result.add(curr);
// Update indegree of neighbors and add them to
// the queue if they become ready
for (int c : adj.get(curr)) {
indegree[c]--;
if (indegree[c] == 0) {
q.add(c);
}
}
// If there are multiple elements ready at the
// same time, it's not the only supersequence
if (q.size() > 1) {
return false;
}
}
// Check if the resulting sequence is the same as
// the given array and has the same length
return result.equals(arr);
}
// Driver code
public static void main(String[] args)
{
List<Integer> arr = Arrays.asList(1, 2, 3);
List<List<Integer> > sequences = Arrays.asList(
Arrays.asList(1, 2), Arrays.asList(1, 3));
boolean result
= sequenceReconstruction(arr, sequences);
if (result) {
System.out.println("True");
}
else {
System.out.println("False");
}
}
}
// This code is contributed by shivamgupta310570
from collections import deque
# Function to check if arr is the only shortest
# supersequence for sequences
def sequenceReconstruction(arr, sequences):
n = len(arr)
# Create adjacency list to represent dependencies
# between elements
adj = [[] for _ in range(n + 1)]
# Store indegree of each element (number of elements
# that must appear before it)
indegree = [0] * (n + 1)
# Build the dependency graph
for seq in sequences:
for j in range(len(seq) - 1):
adj[seq[j]].append(seq[j + 1])
indegree[seq[j + 1]] += 1
# Perform topological sort using a queue
q = deque()
result = []
# Add elements with indegree 0 to the queue (starting
# points)
for i in range(1, n + 1):
if indegree[i] == 0:
q.append(i)
# If there are multiple elements with indegree 0, it's
# not the only supersequence
if len(q) > 1:
return False
# Process elements in topological order
while q:
curr = q.popleft()
result.append(curr)
# Update indegree of neighbors and add them to the
# queue if they become ready
for c in adj[curr]:
indegree[c] -= 1
if indegree[c] == 0:
q.append(c)
# If there are multiple elements ready at the same
# time, it's not the only supersequence
if len(q) > 1:
return False
# Check if the resulting sequence is the same as the
# given array and has the same length
return result == arr
# Driver code
if __name__ == "__main__":
arr = [1, 2, 3]
sequences = [[1, 2], [1, 3]]
result = sequenceReconstruction(arr, sequences)
if result:
print("True")
else:
print("False")
# This code is contributed by Ayush Mishra
function sequenceReconstruction(arr, sequences) {
const n = arr.length;
// Create adjacency list to represent dependencies between elements
const adj = Array.from({ length: n + 1 }, () => []);
// Store indegree of each element (number of elements that must appear before it)
const indegree = Array(n + 1).fill(0);
// Build the dependency graph
sequences.forEach(seq => {
for (let j = 0; j < seq.length - 1; j++) {
adj[seq[j]].push(seq[j + 1]);
indegree[seq[j + 1]]++;
}
});
// Perform topological sort using a queue
const q = [];
const result = [];
// Add elements with indegree 0 to the queue (starting points)
for (let i = 1; i <= n; i++) {
if (indegree[i] === 0) {
q.push(i);
}
}
// If there are multiple elements with indegree 0, it's not the only supersequence
if (q.length > 1) {
return false;
}
// Process elements in topological order
while (q.length > 0) {
const curr = q.shift();
result.push(curr);
// Update indegree of neighbors and add them to the queue if they become ready
for (const c of adj[curr]) {
indegree[c]--;
if (indegree[c] === 0) {
q.push(c);
}
}
// If there are multiple elements ready at the same time, it's not the
//only supersequence
if (q.length > 1) {
return false;
}
}
// Check if the resulting sequence is the same as the given array
//and has the same length
return JSON.stringify(result) === JSON.stringify(arr);
}
// Driver code
const arr = [1, 2, 3];
const sequences = [[1, 2], [1, 3]];
const result = sequenceReconstruction(arr, sequences);
if (result) {
console.log("True");
} else {
console.log("False");
}
Output
False
Time Complexity: O(S + N), where S is the total number of elements in all sequences and N is the number of elements in the array arr.
Auxiliary Space: O(S + N)