-
Notifications
You must be signed in to change notification settings - Fork 155
/
Copy pathsequence-reconstruction.js
182 lines (150 loc) · 4.13 KB
/
sequence-reconstruction.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* 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
*/
/**
* DFS Solution
*
* @param {number[]} org
* @param {number[][]} seqs
* @return {boolean}
*/
export const sequenceReconstructionDFS = (org, seqs) => {
// Step 1. Build the graph using adjacency list and indgree map
const { adjList, indegree } = buildGraph(seqs);
// Step 2. Find all topological sort
const visited = new Set();
const results = [];
dfs(adjList, indegree, visited, results, []);
return results.length === 1 && results[0].toString() === org.toString();
};
/**
* BFS Solution
*
* @param {number[]} org
* @param {number[][]} seqs
* @return {boolean}
*/
export const sequenceReconstructionBFS = (org, seqs) => {
// Step 1. Build the graph using adjacency list and indgree map
const { adjList, indegree } = buildGraph(seqs);
// Step 2. BFS
const verticies = [...adjList.keys()];
if (verticies.length !== org.length) {
return false;
}
// Create a queue and enqueue all vertices with indegree 0
const queue = verticies.filter(u => indegree.get(u) === 0);
// Initialize count of visited vertices
let index = 0;
while (queue.length > 0) {
const size = queue.length;
if (size > 1) {
return false;
}
const u = queue.shift();
if (u !== org[index++]) {
return false;
}
adjList.get(u).forEach(v => {
indegree.set(v, indegree.get(v) - 1);
if (indegree.get(v) === 0) {
queue.push(v);
}
});
}
return index === org.length;
};
const dfs = (adjList, indegree, visited, results, solution) => {
const verticies = [...adjList.keys()];
// To indicate whether all topological are found or not
let flag = false;
for (let i = 0; i < verticies.length; i++) {
const u = verticies[i];
// If indegree is 0 and not yet visited then only choose that vertex
if (indegree.get(u) === 0 && !visited.has(u)) {
// Meaning that we still have nodes to traverse, we are not finished yet
flag = true;
// Reducing indegree of adjacent vertices
adjList.get(u).forEach(v => {
indegree.set(v, indegree.get(v) - 1);
});
// Including in result
solution.push(u);
visited.add(u);
dfs(adjList, indegree, visited, results, solution);
// Resetting visited, res and indegree for backtracking
visited.delete(u);
solution.pop();
adjList.get(u).forEach(v => {
indegree.set(v, indegree.get(v) + 1);
});
}
}
// We reach here if all vertices are visited.
// So we add the solution here
if (!flag) {
results.push(solution.slice());
}
};
const buildGraph = seqs => {
const adjList = new Map();
const indegree = new Map();
seqs.forEach(seq => {
for (let i = 0; i < seq.length; i++) {
const v = seq[i];
if (!adjList.has(v)) {
adjList.set(v, []);
indegree.set(v, 0);
}
if (i > 0) {
const u = seq[i - 1];
adjList.get(u).push(v);
indegree.set(v, indegree.get(v) + 1);
}
}
});
return { adjList, indegree };
};