Skip to content

Commit eb6d7b0

Browse files
committed
Runtime: 4875 ms (Top 5.9%) | Memory: 114.72 MB (Top 34.5%)
1 parent d8bcd6c commit eb6d7b0

File tree

1 file changed

+88
-42
lines changed

1 file changed

+88
-42
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,96 @@
1+
// Runtime: 4875 ms (Top 5.9%) | Memory: 114.72 MB (Top 34.5%)
2+
13
/**
24
* @param {number[]} edges
35
* @return {number}
46
*/
5-
var longestCycle = function(edges) {
6-
// visited array will be -1 if not visited or index of first visited node
7-
const visited = Array(edges.length).fill(-1)
8-
let ans = -1
9-
10-
for (let i = 0; i < edges.length; i++) {
11-
12-
// Since one node could be part of only one solution, only compute if it is not already visited.
13-
if (visited[i] !== -1) continue;
14-
15-
// detect cycle: check if node is already visited
16-
// if it was visited and the visited[i] === i,
17-
// it means we came to this node during this iteration
18-
// hence find the length
19-
20-
let currNode = i
21-
22-
while(currNode !== -1) {
23-
// if not already visited, mark as visited
24-
if (visited[currNode] === -1) {
25-
visited[currNode] = i
26-
currNode = edges[currNode]
27-
continue;
28-
}
29-
30-
// if already visited, and value is equal to current index
31-
// it means we came to node during this iteration, hence we found the cycle
32-
if (visited[currNode] === i) {
33-
// find the cycle length
34-
let currCycleLen = 1
35-
let cycleStartNode = currNode
36-
currNode = edges[currNode]
37-
38-
// revisit all the nodes since first cycle node and note the length
39-
while(currNode !== cycleStartNode) {
40-
currCycleLen++
41-
currNode = edges[currNode]
7+
function getCycleTopology(edges){
8+
const indeg = new Array(edges.length).fill(0);
9+
const queue = [];
10+
const map = {};
11+
for(const src in edges){
12+
const des = edges[src]
13+
if(des >= 0){
14+
indeg[des] ++;
15+
}
16+
map[src] ? map[src].push(des) : map[src] = [des]
17+
}
18+
for(const node in indeg){
19+
if(indeg[node] === 0){
20+
queue.push(node)
21+
}
22+
}
23+
while(queue.length > 0){
24+
const node = queue.shift();
25+
for(const connectedNode of map[node]){
26+
if(connectedNode !== -1){
27+
indeg[connectedNode] --;
28+
if(indeg[connectedNode] === 0){
29+
queue.push(connectedNode);
4230
}
43-
ans = Math.max(currCycleLen, ans)
4431
}
45-
break;
4632
}
4733
}
48-
// console.log(visited)
49-
return ans
50-
};
34+
return indeg
35+
}
36+
class DisjointSet{
37+
constructor(n){
38+
this.n = n;
39+
this.root = new Array(n).fill(0).map((_,i) => i);
40+
this.rank = new Array(n).fill(1);
41+
42+
}
43+
find(x){
44+
if(x === this.root[x]) return x;
45+
return this.root[x] = this.find(this.root[x]);
46+
}
47+
union(x,y){
48+
const x_root = this.find(x);
49+
const y_root = this.find(y);
50+
51+
if(this.rank[x_root] < this.rank[y_root]){
52+
[this.rank[x_root] , this.rank[y_root]] = [this.rank[y_root] , this.rank[x_root]];
53+
}
54+
this.root[y_root] = x_root;
55+
if(this.rank[x_root] === this.rank[y_root]) this.rank[x_root] ++;
56+
}
57+
_getGroupsComponentCounts(){
58+
let groups = {};
59+
for(const node of this.root){
60+
const node_root = this.find(node);
61+
groups[node_root] = groups[node_root] +1 || 1
62+
}
63+
return groups
64+
}
65+
getLongestGroupComponentLength(){
66+
let longestLength = 1;
67+
const lengths = this._getGroupsComponentCounts();
68+
for(const length of Object.values(lengths)){
69+
if(length > 1){
70+
longestLength = Math.max(longestLength, length);
71+
}
72+
}
73+
return longestLength > 1 ? longestLength : -1;
74+
}
75+
}
76+
var longestCycle = function(edges) {
77+
const djs = new DisjointSet(edges.length);
78+
let res = -1
79+
80+
// topology sort results topology array.
81+
// component with greater than 0 is cyclic component.
82+
// now we need to get groups of cycle since we can't distinguish each cycles with current datas.
83+
const cycleComponent = getCycleTopology(edges);
84+
85+
//with edges info and cycle component data, we can now distinguish each cycle group by union finde
86+
// because each cycle r independent with each other.
87+
for(const src in edges){
88+
const des = edges[src];
89+
if(cycleComponent[src] && cycleComponent[des]){
90+
djs.union(src, des);
91+
}
92+
}
93+
res = djs.getLongestGroupComponentLength()
94+
return res
95+
};
96+

0 commit comments

Comments
 (0)