Подсчет перекрытий целых диапазонов

Я немного пошатнулся в этом алгоритме.

Скажем, что существует четыре диапазона целых чисел. Каждый диапазон имеет значение Start и End.

Range A: 0,5
Range B: 4,12
Range C: 2,10
Range D: 8,14

Из этих значений я хотел бы получить новый набор, который подсчитывает количество диапазонов, попадающих в определенный интервал int. Каждый из них имел бы значения Start, End и Count, создавая что-то вроде этого:

(Start, End, Count)
0,1,1   (Only 1 range (A) falls between 0 and 1 inclusive)
2,3,2   (2 ranges (A,C))
4,5,3   (3 ranges (A,B,C))
6,7,2   (2 ranges (B,C))
8,10,3  (3 ranges (B,C,D))
11,12,2 (2 ranges (B,D))
13,14,1 (1 range (D))

Это имеет смысл? Какой хороший способ подойти к алгоритму?

Ответ 1

Вы можете решить это в O (N ln N) времени (для сортировки), за которым следует такое же количество времени для вывода результатов. Если диапазон чисел велик, O (N ln N) лучше, чем время O (M · N) метода, предложенного в комментарии (где M = полный диапазон чисел, охватываемых диапазонами).

Сортируйте диапазоны N в порядке возрастания, введенные по значению "Старт", скажем в массиве S. Инициализируйте пустую очередь приоритетов P. Инициализируйте счетчик глубины D до нуля и текущий "досягаемость" до R = S [0].start.

В то время как S [i].Start = R, нажимайте S [i].End на P и продвигайте я и D. Когда S [i].Start > R, вы получите кортеж (R, p.top, D), Поп P в R, а затем уменьшите D на единицу и поп P в то время как P.top == R.

Повторите вышеприведенный абзац, пока i<N.

Ответ 2

function checkOverlap(arr){
  var overlaps = {}, i, j;
  // match each item against all others BUT itself
  for( i=0; i < arr.length; i++ )
      for( j=0; j < arr.length; j++ )
          if( arr[i] !== arr[j] && arr[i][1] < arr[j][2] && arr[j][1] < arr[i][2] )
            overlaps[arr[i][0]] = 1;

  return Object.keys(overlaps);
}

Запустите его с массивом диапазонов, например:

[
  ["a", 10, 12], 
  ["b", 20, 30], 
  ["c", 29, 30], 
  ["d", 15, 95], 
  ["e", 195, 196]
];

демонстрация Playgroud

Ответ 3

Диапазон x пересекает диапазон ввода y, если:

x.End >= y.Start AND y.End >= x.Start

Итак, для данного ввода просто пройдите по вашей коллекции диапазонов и посмотрите, какие из них удовлетворяют указанному выше условию.

Если ваш набор диапазонов диапазонов не меняется очень часто, и ваша коллекция диапазонов становится намного больше, чем указано в описании проблемы, затем сначала сортируйте их, чтобы вы могли более эффективно искать диапазоны, которые пересекаются ваш ввод, а не цикл через все из них.

Если данный набор диапазонов изменяется часто, сортировка может быть слишком дорогостоящей, и тогда было бы разумнее просто циклически перебирать все из них каждый раз.