- Удалить хакерский возврат, прокомментированный в прокомментированном листинге выше
Это не хакерский возврат. Рекурсивный алгоритм всегда нуждается в базовом случае, и start >= end
- это именно тот базовый случай, от которого зависит эта рекурсия.
Предыдущее return
не является обычным. Если для val
разрешены все целочисленные значения, то val === arr[mid].top
- редкий случай, и на самом деле он не требует особой обработки. Подумайте, что должно произойти, когда val
равно arr[mid].top + 1
. Он должен быть таким же (при условии, что height
больше 1).
Также первый return
, когда mid < 0
не требуется, если вы не планируете вызывать эту функцию с отрицательными значениями для любого start
или end
. Фактически вы рискуете сделать это для end
в рекурсивных вызовах, но посмотрите следующий пункт о том, как этого избежать.
Найдите первую строку, в которой верхнее значение строки ниже искомого значения
В настоящее время ваш алгоритм неверен: когда вместо 140 вы передаете 120 во втором вызове, возвращаемое значение на 2 единицы меньше, в то время как вы "поднимаетесь" только на одну строку.
Я бы предложил определить end
как первый индекс после текущего диапазона. Это соответствует определению параметров для таких функций, как .slice
.
Было бы здорово, если бы не увеличивать lastIndex на 1
Вы не должны стремиться к этому, поскольку логично, что если вы используете одну и ту же функцию для поиска начального row и конечную строку, вы хотите выбрать еще одну строку, чем lastIndex - firstIndex
. Так что просто добавьте 1 и не беспокойтесь об этом.
Вот фиксированный алгоритм:
function rowBinarySearch(arr, val, start = 0, end = arr.length) {
if (start >= end) return end - 1; // base case
const mid = (start + end) >> 1; // Use shift, so you don't need to `floor`.
return val < arr[mid].top
? rowBinarySearch(arr, val, start, mid)
: rowBinarySearch(arr, val, mid + 1, end);
}
// Demo
const rows = Array.from({length: 7}, (_, id) => ({
id, top: id*25, bottom: id*25+25, height: 25
}));
const firstIndex = rowBinarySearch(rows, 30);
const lastIndex = rowBinarySearch(rows, 140, firstIndex);
console.log(rows.slice(firstIndex, lastIndex + 1).map(JSON.stringify).join("\n"));