Проблема кодирования: Учитывая строку S и символ C, найдите расстояние для всех символов в строке к символу C в строке с. Вы можете предположить, что символ C появится хотя бы один раз в строке. Эта проблема была недавно спросила Uber.
Пример:
Например, дано shortest_dist ('helloworld', 'l')
, вы должны вернуть [2, 1, 0, 0, 1, 2, 2, 1, 0, 1]
.
Решение проблемы:
1) Техника: раздвижные окна (в этом случае два окна справа и влево)
Запуск окна и конечные указатели:
Начальные и конечные указатели окна позволяют нам пройти через цепь, увеличивая или уменьшая размер окна, в начале указатель «конец» является единственным, который увеличивается, начальный указатель сохраняет положение до этого. Чар появляется на сцене. С появлением CHAR, Pivot обновляется, размер окна и расстояния между поворотом и элементами, которые сформировали окно до этого момента, обновляются.
Измените размер окна:
Мы можем изменить размер окна, когда мы находим вхождение персонажа в. Индекс «конец» окна проходит через всю цепочку, и начало поддерживает положение, пока мы не найдем pivot = (Вступления в Чар).
Вращаться:
Переменные поворота позволяют нам иметь контрольную точку для последнего появления в цепочке, с этим поворотом мы рассчитаем расстояние между конечным указателем и последним появлением CHAR.
Большой O (n):
Короче говоря, могу сказать, что это решение имеет O (N * M), где «n» – это длина «ST» и «M» – это вхождения «CHAR». Таким образом, внутренний цикл просто для обновления указателя «старта» и «pivot», чем больше случаев персонажа, тем больше раз эта цикл будет работать. Наконец, O (n) – лучший шаблон для описания поведения этих алгоритмов. Мы подчеркиваем факт использования двух окон, чтобы пройти через цепочку, это уменьшается в определенной степени размер циклов обновлений.
Код:
function shortestDist(st, char) { let len = st.length - 1 let [ winLeftStart, winLeftEnd, winRightStart, winRightEnd ] = [0, 0, len, len]; let [pivotLeft, pivotRight] = [null, null]; let dist = []; while (winLeftEnd <= len) { /** Window Left*/ if (st[winLeftEnd] === char) { pivotLeft = winLeftEnd; while (winLeftStart <= pivotLeft) { dist[winLeftStart] = pivotLeft - winLeftStart; ++winLeftStart; } } if (!!pivotLeft) { if (dist[winLeftEnd]) { //End when have first match in dist dist[winLeftEnd] = dist[winLeftEnd] < winLeftEnd - pivotLeft ? dist[winLeftEnd] : winLeftEnd - pivotLeft; return dist; } dist[winLeftEnd] = winLeftEnd - pivotLeft; } /** Window right*/ if (st[winRightEnd] === char) { pivotRight = winRightEnd; while (winRightStart >= pivotRight) { dist[winRightStart] = winRightStart - pivotRight; --winRightStart; } } else if (!!pivotRight) { dist[winRightEnd] = pivotRight - winRightEnd; } /** Grow Windows*/ --winRightEnd; ++winLeftEnd; } return []; }
Простой тест:
console.log(shortestDist('helloworld', 'l')) // h e l l o w o r l d // resp. [2, 1, 0, 0, 1, 2, 2, 1, 0, 1] // 0 1 2 3 4 5 6 7 8 9
Вы можете проверить Код по @ difo23.
Оригинал: “https://dev.to/difo23/technique-sliding-windows-algorithms-55oe”