// Interval graph coloring algorithm, by Twal class IntervalColoration { constructor (intervals) { this.intervals = intervals; this.n = this.intervals.length; this.computeInterferenceGraph(); this.computePEO(); this.computeColoration(); } computeInterferenceGraph() { this.adj = new Array(this.n); for (let i = 0; i < this.n; ++i) { this.adj[i] = []; } for (let i = 0; i < this.n; ++i) { for (let j = 0; j < i; ++j) { let inti = this.intervals[i]; let intj = this.intervals[j]; if (inti[0] < intj[1] && intj[0] < inti[1]) { this.adj[i].push(j); this.adj[j].push(i); } } } } //Perfect elimination order using Maximum Cardinality Search //Runs in O(n^2), could be optimized in O(n log n) computePEO() { let marked = new Array(this.n); let nbMarkedNeighbor = new Array(this.n); this.perm = new Array(this.n); for (let i = 0; i < this.n; ++i) { marked[i] = false; nbMarkedNeighbor[i] = 0; } for (let k = this.n-1; k >= 0; --k) { let maxi = -1; for (let i = 0; i < this.n; ++i) { if (!marked[i] && (maxi == -1 || nbMarkedNeighbor[i] >= nbMarkedNeighbor[maxi])) { maxi = i; } } for (let i = 0; i < this.adj[maxi].length; ++i) { nbMarkedNeighbor[this.adj[maxi][i]] += 1; } this.perm[maxi] = k; marked[maxi] = true; } // console.log(this.perm); } computeColoration() { this.colors = new Array(this.n); let isColorUsed = new Array(this.n); for (let i = 0; i < this.n; ++i) { this.colors[i] = -1; isColorUsed[i] = false; } for (let i = 0; i < this.n; ++i) { let ind = this.perm[i]; for (let j = 0; j < this.adj[ind].length; ++j) { let neigh = this.adj[ind][j]; if (this.colors[neigh] >= 0) { isColorUsed[this.colors[neigh]] = true; } } for (let j = 0; j < this.n; ++j) { if (!isColorUsed[j]) { this.colors[ind] = j; break; } } for (let j = 0; j < this.adj[ind].length; ++j) { let neigh = this.adj[ind][j]; if (this.colors[neigh] >= 0) { isColorUsed[this.colors[neigh]] = false; } } } } }