Маркировка общих участков нескольких наборов отрезков

Один раз преобразуйте интервалы в события начала и конца, отсортируйте координаты и ведите счётчики активных цветов. Между соседними координатами набор цветов постоянен.

Короткий ответ

Что ответить на собеседовании

Один раз преобразуйте интервалы в события начала и конца, отсортируйте координаты и ведите счётчики активных цветов. Между соседними координатами набор цветов постоянен.

Подробный разбор

Ответ с пояснениями

Условие

Имеются три разных набора отрезков. Нужно определить все участки, где они пересекаются, отметить такие пересечения как отдельные новые отрезки (например, пересечение наборов green и yellow отмечаем как новый отрезок – см. exampleResult4), вырезать их из исходных наборов и вывести последовательность получившихся отрезков в диапазоне от 0 до 100.

// Мнемоники отрезков
const Task4 = () => {
    type IMnemo = "green" | "yellow" | "red"
    //Тип для отрезка - начало и конец
    interface IInterval {
        start: number,
        end: number
    }
    type ISourceIntervals = Record<IMnemo, IInterval[]>

    //Тип ответа
    interface IExpectedResult extends IInterval {
        mnemo: IMnemo[],
    }
    //Исходные отрезки
    const sourceData: ISourceIntervals = {
        green: [{ start: 0, end: 30 }, { start: 90, end: 100 }],
        yellow: [{ start: 20, end: 40 }, { start: 50, end: 70 }],
        red: [{ start: 10, end: 50 }, { start: 70, end: 90 }],
    }

    //Ожидаемый результат
    const expectedResult: IExpectedResult[] = [
        { "mnemo": ["green"], start: 0, end: 10 },
        { "mnemo": ["green", "red"], start: 10, end: 20 },
        { "mnemo": ["green", "yellow", "red"], start: 20, end: 30 },
        { "mnemo": ["yellow", "red"], start: 30, end: 40 },
        { "mnemo": ["red"], start: 40, end: 50 },
        { "mnemo": ["yellow"], start: 50, end: 70 },
        { "mnemo": ["red"], start: 70, end: 90 },
        { "mnemo": ["green"], start: 90, end: 100 },
    ]

    // Реализовать внутри этой функции оптимальным способом, перебор исходного массива
    // может быть только один! Допускается формирования дополнительных массивов/объектов
    const getResult = (sourceIntervals: ISourceIntervals): IExpectedResult[] => {
        return expectedResult
    }

    //Это выведет результат её работы справа
    return { expectedResult: expectedResult, result: getResult(sourceData) }
}

//Вспомогательные функции
const showTaskResult =(task: number, taskResult: {result: any, expectedResult: any}) => {
    console.log(`---Результат задачи ${task}---`)
    console.log('Ожидаемый: ', taskResult.expectedResult)
    console.log('Из функции: ', taskResult.result)
    console.log('')
}


showTaskResult(4, Task4())

Ответ

Один раз преобразуйте интервалы в события начала и конца, отсортируйте координаты и ведите счётчики активных цветов. Между соседними координатами набор цветов постоянен.

function getResult(source) {
  const colors = ['green', 'yellow', 'red'];
  const events = new Map();
  const add = (point, color, delta) => {
    if (!events.has(point)) events.set(point, [0, 0, 0]);
    events.get(point)[color] += delta;
  };
  colors.forEach((color, index) => {
    for (const { start, end } of source[color]) {
      if (!(0 <= start && start < end && end <= 100)) throw new RangeError('Неверный интервал');
      add(start, index, 1); add(end, index, -1);
    }
  });
  const points = [...events.keys()].sort((a, b) => a - b);
  const active = [0, 0, 0], result = [];
  for (let i = 0; i + 1 < points.length; i++) {
    const point = points[i];
    events.get(point).forEach((delta, index) => { active[index] += delta; });
    const mnemo = colors.filter((_, index) => active[index] > 0);
    if (!mnemo.length) continue;
    const last = result[result.length - 1];
    if (last && last.end === point && last.mnemo.join() === mnemo.join()) last.end = points[i + 1];
    else result.push({ mnemo, start: point, end: points[i + 1] });
  }
  return result;
}

Интервалы трактуются как [start, end), точки нулевой длины не выводятся. Незакрашенные промежутки пропускаются. Счётчики корректны и при пересечении интервалов одного цвета. Исходный набор обходится один раз, сортировка событий даёт O(n log n); порядок цветов совпадает с примером.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее