Цель этого типа интервью - увидеть, как вы подходите к новым проблемам.Если вы уже знаете ответ, это, несомненно, ваша заслуга, но на самом деле это не ответ на вопрос.Интервьюеру интересно наблюдать за тем, как вы решаете проблемы.
По этой причине часто интервьюер добавляет дополнительные ограничения, пытаясь вывести вас из зоны комфорта и посмотреть, как вы справляетесь.
Я думаю, это здорово, что вы знали этот факт о распознавании чисел Фибоначчи.Я бы не узнал об этом без консультации с Википедией.Это интересный факт, но помогает ли он решить проблему?
По-видимому, необходимо вычислить 5n²±4
, вычислить квадратные корни и затем убедиться, что один из них является целым числом.Имея доступ к реализации с плавающей запятой с достаточной точностью, это не будет слишком сложным.Но насколько это точно?Если n
может быть произвольным 32-битным числом со знаком, то n²
, очевидно, не вписывается в 32 бита.Фактически, 5n²+4
может составлять до 65 бит, не считая знакового бита.Это намного выше точности double
(обычно 52 бита) и даже long double
, если доступно.Поэтому вычисление точного квадратного корня будет проблематичным.
Конечно, нам на самом деле не нужны точные вычисления.Мы можем начать с аппроксимации, возвести ее в квадрат и посмотреть, будет ли она на четыре больше или на четыре меньше 5n²
.И легко понять, как вычислить правильное предположение: оно будет очень близко к n×√5
.Используя хорошее предварительно вычисленное приближение √5
, мы можем легко выполнить это вычисление без необходимости использования плавающей запятой, без деления и без функции sqrt.(Если приближение не точное, нам может потребоваться скорректировать результат вверх или вниз, но это легко сделать с помощью идентификатора (n+1)² = n²+2n+1
; как только мы получим n²
, мы можем вычислить (n+1)²
только с добавлением.
Нам все еще нужно решить проблему точности, поэтому нам понадобится какой-то способ работы с 66-битными целыми числами, но нам нужно только реализовать сложение и умножение натуральных чисел, что значительно проще, чем полноепакет bignum. Действительно, если мы сможем доказать, что наша оценка квадратного корня достаточно близка, мы могли бы безопасно выполнить проверку по модулю 2³¹.
Таким образом, аналитическое решение можно заставить работать, но перед тем, как окунуться в него,мы должны спросить, является ли это лучшим решением. Одна из наиболее распространенных проблем субоптимального программирования отчаянно цепляется за первую идею, с которой вы приходите, даже когда ее сложности становятся все более очевидными. Это будет одна из вещей, которую интервьюер хочет узнать о вас.: насколько вы гибки, когда представлены с новой информациейили новые требования.
Итак, какие еще способы узнать, является ли n
числом Фибоначчи.Один интересный факт заключается в том, что если n
равно Fib(k)
, то k
является полем log<sub>φ</sub>(k×√5 + 0.5)
.Поскольку log<sub>φ</sub>
легко вычисляется из log<sub>2</sub>
, который, в свою очередь, может быть аппроксимирован простой побитовой операцией, мы могли бы попытаться найти аппроксимацию k
и проверить ее, используя классическую O(log k)
рекурсию для вычисления Fib(k)
.Ни одно из вышеприведенных чисел не превышает емкость 32-разрядного знакового типа.
Еще проще: мы можем просто пройти цикл Фибоначчи в цикле, проверяя, достигли ли мы целевого числа.Нужно всего 47 петель.Кроме того, эти 47 чисел можно предварительно рассчитать и выполнить поиск с помощью бинарного поиска, используя намного меньше, чем разрешенные вами байты 1 КБ.