You are given an integer array nums of length n where nums is a permutation of the integers in the range [1, n]. You are also given a 2D integer array sequences where sequences[i] is a subsequence of nums.
Check if nums is the shortest possible and the only supersequence. The shortest supersequence is a sequence with the shortest length and has all sequences[i] as subsequences.
There could be multiple valid supersequences for the given array sequences. For example, for sequences = [[1,2],[1,3]], there are two shortest supersequences, [1,2,3] and [1,3,2]. While for sequences = [[1,2],[1,3],[1,2,3]], the only shortest supersequence possible is [1,2,3].
Return true if nums is the only shortest supersequence for sequences, or false otherwise.
A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements.
Input & Output
Example 1 — Unique Sequence
$Input:nums = [1,2,3], sequences = [[1,2,3],[1]]
›Output:true
💡 Note:The sequences force a unique ordering: 1 must come first (from [1]), then 2, then 3 (from [1,2,3]). Only [1,2,3] satisfies all constraints.
Example 2 — Multiple Valid Orderings
$Input:nums = [1,2,3], sequences = [[1,2],[1,3]]
›Output:false
💡 Note:Both [1,2,3] and [1,3,2] satisfy the constraints. Since there are multiple valid shortest supersequences, return false.
Use topological sorting to determine if there's a unique ordering. Build a directed graph from sequences, then check if topological sort produces exactly one valid path. The key insight is that uniqueness requires having exactly one node with indegree 0 at each step. Time: O(V + E), Space: O(V + E)
Common Approaches
✓
Brute Force Validation
⏱️ Time: O(n × m)
Space: O(1)
First validate that all given sequences are subsequences of nums, then check if any other permutation could work. This approach checks all constraints but doesn't efficiently determine uniqueness.
Topological Sort
⏱️ Time: O(V + E)
Space: O(V + E)
Create a directed graph from the sequences where an edge from A to B means A must come before B. Then perform topological sort to check if there's exactly one valid ordering.
Brute Force Validation — Algorithm Steps
Step 1: Verify all sequences are subsequences of nums
Step 2: Check if constraints force unique ordering
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Input
nums=[1,2,3], sequences=[[1,2],[1,3]]
2
Validate
Check each sequence is subsequence of nums
3
Result
Basic validation complete
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// Use adjacency list instead of 10001x10001 matrix (would be ~400MB)
#define MAXN 10001
#define MAXEDGES 1000000
static int graphHead[MAXN]; // head of adjacency list for each node
static int graphNext[MAXEDGES];
static int graphTo[MAXEDGES];
static int edgeCount;
static int indegree[MAXN];
static int result[MAXN];
static int nums[MAXN];
static int sequences[1000][1000];
static int sequencesColSize[1000];
// Simple hash set for edge deduplication: store edges as from*MAXN+to
// We'll use a visited array per node approach instead during build
static bool edgeExists[MAXN][MAXN / 32 + 1]; // bit array won't work cleanly; use flat bool
// Actually to avoid huge memory, track via a small check during insert
// We reset indegree carefully. For dedup, use a marker array per source reset each time.
// Simpler: just use a boolean 2D... but that's 100M bools = 100MB, too big.
// Use a hash set approach with chaining.
#define HASH_SIZE (1 << 20)
#define HASH_MASK (HASH_SIZE - 1)
typedef struct HashNode {
int key; // from * MAXN + to
struct HashNode* next;
} HashNode;
static HashNode hashPool[MAXEDGES];
static int hashPoolIdx;
static HashNode* hashTable[HASH_SIZE];
static void hashClear() {
memset(hashTable, 0, sizeof(hashTable));
hashPoolIdx = 0;
}
static bool hashInsert(int from, int to) {
int key = from * MAXN + to;
int h = ((unsigned)key * 2654435761u) & HASH_MASK;
for (HashNode* n = hashTable[h]; n; n = n->next) {
if (n->key == key) return false; // already exists
}
HashNode* node = &hashPool[hashPoolIdx++];
node->key = key;
node->next = hashTable[h];
hashTable[h] = node;
return true;
}
static void addEdge(int from, int to) {
graphNext[edgeCount] = graphHead[from];
graphTo[edgeCount] = to;
graphHead[from] = edgeCount++;
}
// Parse a 1D array string like "[1,2,3]" into arr, returns size
static int parseArray(const char* s, int* arr) {
int size = 0;
// Find opening bracket
const char* p = s;
while (*p && *p != '[') p++;
if (!*p) return 0;
p++; // skip '['
while (*p && *p != ']') {
while (*p == ' ' || *p == ',') p++;
if (*p == ']' || *p == '\0') break;
char* endptr;
int num = (int)strtol(p, &endptr, 10);
if (endptr != p) {
arr[size++] = num;
p = endptr;
} else {
p++;
}
}
return size;
}
// Parse a 2D array string like "[[1,2],[3,4]]"
// Uses depth-tracking approach from C++ reference
static int parse2DArray(const char* s) {
int seqCount = 0;
// Find outer opening bracket
const char* p = s;
while (*p && *p != '[') p++;
if (!*p) return 0;
p++; // skip outer '['
// Track current inner array as a string buffer
char current[10000];
int curLen = 0;
int depth = 0;
while (*p && !(*p == ']' && depth == 0)) {
if (*p == '[') {
depth++;
current[curLen++] = *p;
} else if (*p == ']') {
depth--;
current[curLen++] = *p;
if (depth == 0) {
current[curLen] = '\0';
sequencesColSize[seqCount] = parseArray(current, sequences[seqCount]);
seqCount++;
curLen = 0;
}
} else if (*p == ',' && depth == 0) {
// skip comma between inner arrays
} else {
current[curLen++] = *p;
}
p++;
}
return seqCount;
}
static bool solution(int* numsArr, int numsSize, int sequencesSize) {
int n = numsSize;
if (n == 0) {
return sequencesSize == 0;
}
// Reset graph structures
memset(graphHead, -1, sizeof(int) * (n + 2)); // we'll init per node below
for (int i = 0; i < numsSize; i++) {
graphHead[numsArr[i]] = -1;
}
edgeCount = 0;
hashClear();
memset(indegree, 0, sizeof(indegree));
// Build lookup for valid numbers and coverage check
static bool allNums[MAXN];
static bool covered[MAXN];
memset(allNums, 0, sizeof(bool) * MAXN);
memset(covered, 0, sizeof(bool) * MAXN);
for (int i = 0; i < numsSize; i++) {
allNums[numsArr[i]] = true;
}
for (int i = 0; i < sequencesSize; i++) {
for (int j = 0; j < sequencesColSize[i]; j++) {
int num = sequences[i][j];
if (!allNums[num]) return false;
covered[num] = true;
}
}
// All elements must be covered
for (int i = 0; i < numsSize; i++) {
if (!covered[numsArr[i]]) return false;
}
// Add edges from sequence constraints (deduplicated)
for (int i = 0; i < sequencesSize; i++) {
for (int j = 0; j < sequencesColSize[i] - 1; j++) {
int from = sequences[i][j];
int to = sequences[i][j + 1];
if (hashInsert(from, to)) {
addEdge(from, to);
indegree[to]++;
}
}
}
// Topological sort (BFS / Kahn's algorithm) with uniqueness check
static int queue[MAXN];
int head = 0, tail = 0;
for (int i = 0; i < numsSize; i++) {
if (indegree[numsArr[i]] == 0) {
queue[tail++] = numsArr[i];
}
}
int resultSize = 0;
while (head < tail) {
// More than one candidate means ordering is not unique
if (tail - head > 1) return false;
int curr = queue[head++];
result[resultSize++] = curr;
for (int e = graphHead[curr]; e != -1; e = graphNext[e]) {
int nb = graphTo[e];
indegree[nb]--;
if (indegree[nb] == 0) {
queue[tail++] = nb;
}
}
}
// Must have processed all nodes and match nums exactly
if (resultSize != n) return false;
for (int i = 0; i < n; i++) {
if (result[i] != numsArr[i]) return false;
}
return true;
}
int main() {
static char line1[1000000], line2[1000000];
if (!fgets(line1, sizeof(line1), stdin)) return 1;
if (!fgets(line2, sizeof(line2), stdin)) return 1;
line1[strcspn(line1, "\n")] = 0;
line2[strcspn(line2, "\n")] = 0;
int numsSize = parseArray(line1, nums);
int sequencesSize = parse2DArray(line2);
bool res = solution(nums, numsSize, sequencesSize);
printf(res ? "true\n" : "false\n");
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(n × m)
Check each sequence against nums, where m is total elements in sequences
n
2n
✓ Linear Growth
Space Complexity
O(1)
Only using variables for validation
n
2n
✓ Linear Space
32.4K Views
MediumFrequency
~25 minAvg. Time
1.2K Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.