class RangeList {
constructor() {
this.rangeList = [];
}
/**
* Adds a range to the list
* @param {Array<number>} range - Array of two integers that specify
beginning and end of range.
*/
add(range) {
if(this.valid(range)) {
let [start, end] = range;
if(start < end) {
let length = this.rangeList.length;
if(length === 0) {
this.rangeList.push(range);
return;
}
let newRangeList = [];
let hasPush = false;
for(let i = 0; i < length; i++) {
let [curStart, curEnd] = this.rangeList[i];
if(curStart > end) {
newRangeList.push(this.rangeList[i]);
}
else {
if(start > curEnd) {
newRangeList.push(this.rangeList[i]);
}
else {
hasPush = true;
this.insert(curStart, curEnd, start, end, newRangeList)
}
}
}
if(!hasPush) {
newRangeList.push(range);
}
this.rangeList = newRangeList;
}
}
}
/**
* combine range
* egg: [1, 8] ,then add [3, 10], result is [1, 10]
*/
insert(curStart, curEnd, addStart, addEnd, newRangeList) {
let start = Math.min(curStart, addStart);
let end = Math.max(curEnd, addEnd);
let i = newRangeList.length - 1;
while(i >= 0) {
if(start <= newRangeList[i][1] && start >= newRangeList[i][0]) {
newRangeList[i][1] = end;
return;
}
else if(start < newRangeList[i][0]){
break;
}
i--;
}
newRangeList.push([start, end]);
}
/**
* Removes a range from the list
* @param {Array<number>} range - Array of two integers that specify
beginning and end of range.
*/
remove(range) {
if(this.valid(range)) {
let [removeStart, removeEnd] = range;
if(removeStart < removeEnd) {
let length = this.rangeList.length;
let newRange = [];
for(let i = 0; i < length; i++) {
let [curStart, curEnd] = this.rangeList[i];
// egg: [5, 10], then remove [8, 20], result is [5, 8]
if(removeStart > curStart && removeStart < curEnd && removeEnd > curEnd) {
newRange.push([curStart, removeStart]);
}
// egg: [5, 10], then remove [5, 8] or remove [8, 10] or remove [6,8], has 3 cases
else if(removeStart >= curStart && removeEnd <= curEnd) {
if(curStart === removeStart) {
if(curEnd !== removeEnd) {
newRange.push([removeEnd, curEnd]);
}
}
else if(curEnd === removeEnd) {
newRange.push([curStart, removeStart]);
}
else if(curStart !== removeStart && curEnd !== removeEnd) {
newRange.push([curStart, removeStart],[removeEnd, curEnd]);
}
}
// egg: [5, 10], then remove [1, 8], result is [8, 10]
else if(removeStart < curStart && removeEnd > curStart && removeEnd <= curEnd) {
if(removeEnd !== curEnd) {
newRange.push([removeEnd, curEnd])
}
}
else if(removeEnd <= curStart || removeStart > curEnd) {
newRange.push(this.rangeList[i]);
}
}
this.rangeList = newRange;
}
}
}
valid(range) {
if(Array.isArray(range) && range.length === 2) {
return true;
}
return false;
}
/**
* Prints out the list of ranges in the range list
*/
print() {
let res = '';
for(let [start, end] of this.rangeList) {
res += `[${start}, ${end}) `
}
console.log(res);
return res;
}
}
const rl = new RangeList();
rl.add([1, 5]);
rl.print();
// Should display: [1, 5)
rl.add([10, 20]);
rl.print();
// Should display: [1, 5) [10, 20)
rl.add([20, 20]);
rl.print();
// Should display: [1, 5) [10, 20)
rl.add([20, 21]);
rl.print();
// Should display: [1, 5) [10, 21)
rl.add([2, 4]);
rl.print();
// Should display: [1, 5) [10, 21)
rl.add([3, 8]);
rl.print();
// Should display: [1, 8) [10, 21)
rl.remove([10, 10]);
rl.print();
// Should display: [1, 8) [10, 21)
rl.remove([10, 11]);
rl.print();
// Should display: [1, 8) [11, 21)
rl.remove([15, 17]);
rl.print();
// Should display: [1, 8) [11, 15) [17, 21)
rl.remove([3, 19]);
rl.print();
// Should display: [1, 3) [19, 21)
console