#javascript #algorithm
#javascript #алгоритм
Вопрос:
Я хотел использовать функцию, которая делает это:
const input =“hellooooloo”;
const results = getRepeated(input);
console.log(results) // [(2,3), (4,7), (9,10)]
Он возвращает массив массивов индексов начального и конечного индексов последовательно повторяющихся символов из строки.
Вот моя попытка, это O(n ^ 2). Интересно, есть ли более элегантный и эффективный способ достижения этой цели
const input = 'hellooooloo';
const results = getRepeated(input); // // [(2,3), (4,7), (9,10)]
function getRepeated(string) {
const results = []
if(string.length < 2) return results
for(let i = 0; i < string.length - 1; i ) {
if(i > 1 amp;amp; string[i] === string[i-1]) {
continue
}
let startIndex = i
let endIndex = i
for(let j = i 1; j < string.length; j ) {
if(string[i] === string[j]) {
endIndex = j
} else {
break
}
}
if(startIndex !== endIndex) {
results.push([startIndex, endIndex])
}
}
return results
}
Комментарии:
1. Ваш алгоритм не
O(n^2)
является, он естьO(n)
. (Ну, на самом деле, это и то, и другое.) Это происходит из-за логики if … then continue, которая у вас есть в строках 8 и 9. Внутренний цикл (цикл j) выполняет итерацию не более, чем дляO(n)
шагов в целом. Потому что, если цикл j продолжается, скажем, на m шагов, то для следующих m шагов внешний цикл примет ветвь continue в строке 9.
Ответ №1:
Я бы использовал регулярное выражение: сопоставьте и захватите один символ, затем сделайте обратную ссылку на тот же символ столько раз, сколько сможете. Выполните глобальное сопоставление регулярных выражений со строкой. Возьмите все совпадения и сопоставьте их с массивом их индекса и их индексом плюс длина совпадения:
const getRepeated = str => [...str.matchAll(/(.)1 /g)]
.map(({ index, 0: match }) => [index, index match.length - 1]);
const input = "hellooooloo";
const results = getRepeated(input);
console.log(results) // [(2,3), (4,7), (9,10)]
Это O(n)
.
Регулярное выражение означает:
(.)
— Сопоставьте любой символ, поместите его в группу захвата1
— Повторите один и тот же символ, соответствующий этой группе захвата, один или несколько раз
Например, для приведенного здесь примера ввода вы получите следующие совпадения:
[
{ 0: 'll', 1: 'l', index: 2 },
{ 0: 'oooo', 1: 'o', index: 4 },
{ 0: 'oo', 1: 'o', index: 9 },
]
Ответ №2:
Вы могли бы выделить массив символов и проверить, равен ли последний символ фактическому, и скорректировать второй индекс последней пары индексов.
В противном случае проверьте, равен ли фактический символ следующему символу, и создайте новый результирующий набор.
const
getRepeated = ([...array]) => array.reduce((r, c, i, a) => {
if (a[i - 1] === c) r[r.length - 1][1] = i;
else if (c === a[i 1]) r.push([i]);
return r;
}, []),
input = 'hellooooloo',
result = getRepeated(input); // [[2, 3], [4, 7], [9, 10]]
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }