Я бы предложил сначала провести их рефакторинг, чтобы использовать ту же структуру данных, чтобы различия стали более заметными:
function twoNumberSum(array, targetSum) {
let nums = new Set();
for (const num of array) {
const potentialMatch = targetSum - num;
if (nums.has(potentialMatch) {
return [potentialMatch, num].sort((a, b) => a - b)
} else {
nums.add(num)
}
}
return []
}
function twoNumberSum(array, targetSum) {
const nums = new Set();
for (const num of array)
nums.add(num);
// alternatively, use const nums = new Set(array), but the loop is clearer
for (let num of array) {
const missingInc = targetSum - num;
if (missingInc !== value && nums.has(missingInc)) {
return [value, missingInc].sort((a, b) => a - b)
}
}
return [];
}
Прежде чем рассматривать производительность, нам нужно оценитьправильность / эквивалентность: обратите внимание, что вторая функция не работает, когда входное значение содержит дубликаты. Но давайте предположим, что это задано как предварительное условие (никогда не может произойти), и в этом случае результаты всегда одинаковы.
Разница в том, что один подход всегда строит всю карту поиска перед тестированием значений, в то время какдругие строят это на ходу. Хотя оба варианта имеют O(n)
сложность наихудшего случая, для первого подхода сложность наилучшего случая равна O(1)
, а для второго - O(n)
. Какова средняя сложность зависит от того, как распределены ваши входные данные.
Когда я сортирую инструкцию возврата с .sort((a, b) => a - b)
, следует ли это определить как O(log(n))
?
Нет. Сложность сортировки обычно O(n log n)
, но где n
относится к длине массива, который будет отсортирован. В вашем случае вы всегда сортируете массив из двух элементов, который имеет постоянную сложность. Он не зависит от размера ввода n
(предполагается, что array.length
, хотя в некоторых числовых задачах вам также необходимо учитывать размер чисел).