//Function-A
function duplicatesNumber(text) {
var counts = {};
let textLowered = text.toLowerCase();
textLowered.split("").forEach(function (x) {
counts[x] = (counts[x] || 0) + 1;
});
return Object.entries(counts).filter(arr => arr[1] > 1).length
}
//Function-B
function duplicateCount(text) {
return text.toLowerCase().split('').filter(function (val, i, arr) {
return arr.indexOf(val) !== i && arr.lastIndexOf(val) === i;
}).length;
}
//Function-B
let start = performance.now();
console.log(duplicateCount("aaBBcDDcefgheeaas"))
let end = performance.now();
console.log("Function-B: "+ (end-start));
//Function-A
let start1 = performance.now();
console.log(duplicatesNumber("aaBBcDDcefgheeaas"))
let end1 = performance.now();
console.log("Function-A: "+ (end1-start1))
- У меня две функции, они обе делают одно и то же. Вернуть количество дубликатов.
- У меня вопрос об их выступлениях. Я только начал изучать структуры данных и алгоритмы в javascript. Я освещал Big O’Notation. Но, наверное, я не понял.
- Поскольку Function-A имеет для каждого метода, это означает, что это O (n). Разве это не значит, что Function-A должна быть медленнее, чем вторая? Как может быть функция A быстрее, чем функция B?
1 ответ
Сложность времени
- Стоимость функции А $ mathcal {O} left (n right) $
toLowerCase,splitСтоимость $ mathcal {O} left (n right) $forEachСтоимость $ mathcal {O} left (n right) $Object.entries,filterСтоимость $ mathcal {O} left (n right) $counts[x]чтение / запись может стоить $ mathcal {O} left (1 right) $ в среднем
- Стоимость функции B $ mathcal {O} left (n ^ 2 right) $
toLowerCase,splitвсе еще стоит $ mathcal {O} left (n right) $filterСтоимость $ mathcal {O} left (n ^ 2 right) $indexOf,lastIndexOfСтоимость $ mathcal {O} left (n right) $filterповторить вышеуказанную операцию $ mathcal {O} left (n right) $ раз, таким образом $ mathcal {O} left (n cdot n right) $
Потребление времени чаще всего происходило в циклах. Не только forEach, fliter, но также toLowerCase, split, indexOf петли. Вы неправильно подсчитали производительность вложенных циклов.
Также обратите внимание, что нотация большого О предназначена для описания того, насколько быстро увеличивается потребляемое время при увеличении размера ввода. Это не обязательно означает, что алгоритм с лучшей нотацией большого O всегда будет быстрее.
Реализация
- Не используйте
str.split(''), используйте[...str]если вы можете. Разделенный не будет правильно обрабатывать некоторые точки Unicode. Например,[...'𰻝𰻝面'].length3, но'𰻝𰻝面'.split('').length5. - Использовать
Mapесли можете (нет необходимости поддерживать старые браузеры).Objectне идеальный способ использовать в качестве словаря. Только если вы хотите сохранить поддержку ES5, вы можете использоватьObject.create(null)вместо. - Вы можете подсчитать, сколько записей имеет не менее 2 во время итерации, отслеживая, если
count[x] == 2после увеличения. Таким образом, нет необходимости повторятьObject.entriesпозже.

Очень чистый и информативный ответ. Я ценю это!
— Мустафа Гюнер