Два мраморных камня и 100-этажное здание

Один из тех классических вопросов на собеседовании по программированию ...

Вам дают два шарика и говорят, что они сломаются при падении с определенной высоты (и предположительно не пострадают при падении с этой высоты). Затем вы попадаете в 100-этажное здание (предположительно выше определенной высоты) и просите найти самый высокий этаж, с которого вы можете уронить шарик, не разбивая его как можно эффективнее.

Дополнительная информация

  • Вы должны найти правильный этаж (не возможный диапазон)
  • Оба шарика гарантированно лопнут на одном этаже.
  • Предположим, что на смену этажа у вас не требуется времени - учитывается только количество мраморных капель.
  • Предположим, что правильный этаж распределен в здании случайным образом.

Ответов (10)

Решение

Здесь интересно то, как это можно сделать с минимальным количеством капель. Подняться на 50-й этаж и упасть первым будет катастрофой, если ломается 49-й этаж, в результате чего нам придется сделать 50 падений. Мы должны уронить первый шарик на этаж n, где n - максимальное количество требуемых падений. Если мрамор треснет на этаже n, возможно, после этого нам придется сделать n-1 капель. Если шарик не разбивается, мы поднимаемся на этаж 2n-1, а если он разбивается здесь, мы должны в худшем случае бросить второй шарик n − 2 раз. Продолжаем так до 100 этажа и пытаемся разбить его на 3n-2, 4n-3 ....
и n + (n-1) + (n-2) + ... 1 <= 100
n = 14 Требуется максимальное количество капель

Это можно сделать лучше всего с 7 шариками.

Итак, после проголосовавшего ответа, скажем, мрамор треснет как минимум на 49-м этаже.

  1. 50 этаж -> перерывы (от 1 до 50 включительно)
  2. 25 этаж -> не ломается (с 26 на 50)
  3. 37 этаж -> не ломается (с 38 на 50)
  4. 43 этаж -> не ломается (с 44 на 50)
  5. 46 этаж -> не ломается (с 47 на 50)
  6. 48 этаж -> не ломается (49 или 50)
  7. 49-й этаж -> разрывы (49-й, этот шаг действительно необходим, потому что это мог быть минимальный пол, на котором мрамор ломался, на 50-м)

Это можно представить как выполнение двоичного поиска в отсортированном наборе для некоторого k, где мы получаем половину пространства решений с каждой попыткой. Для 100 этажей нам понадобится log2 100 = 6,644 (7 попыток). Имея 7 мраморных плиток, мы можем быть уверены, что это минимальный пол, на который мрамор сможет разбить до 128 этажей.

Если вам нужно общее решение, которое даст вам результат для N этажей (в вашем случае N = 100), вы можете просто решить квадратное уравнение $ x ^ 2 + x-2 \ cdot (N-1) = 0 $ и результат - потолок положительного корня.

Который:

$$ f (N) = потолок \ bigg (\ frac {-1+ \ sqrt {1 + 4 \ cdot2 \ cdot (N-1))}} {2} \ bigg) $$

Каждый из них ломается при падении с одинаковой высоты, или они разные?

Если они такие же, я иду на 50-й этаж и бросаю первый шарик. Если он не сломается, я иду на 75-й этаж и делаю то же самое, пока он не ломается, я продолжаю подниматься на 50% от того, что осталось. Когда он разбивается, я возвращаюсь на один выше, чем был раньше (поэтому, если он сломался на 75-м этаже, я возвращаюсь на 51-й этаж), бросаю второй шарик и поднимаюсь на этаж вверх, пока он не сломается, в этот момент я знаю самый высокий этаж, с которого я могу упасть без разрушения мрамора.

Наверное, не лучший ответ, мне любопытно посмотреть, как ответят другие.

Бросьте первый шарик с 3-го этажа. Если он сломается, вы знаете, что это этаж 1 или 2, поэтому бросьте другой шарик с этажа 2. Если он не сломается, вы обнаружите, что этаж 2 самый высокий. Если он сломается, значит, этаж 1 самый высокий. 2 капли.

Если при падении с 3-го этажа мрамор не разбивается, упадите с 6-го этажа. Если он сломается, вы знаете, что 4-й или 5-й этаж - самый высокий. Бросьте второй шарик с этажа 5. Если он не разбился, вы обнаружили, что 5 - самый высокий. Если да, то 4 этаж - самый высокий. 4 капли.

Продолжать.

3 этажа - максимум 2 капли

6 этажей - максимум 4 капли

9 этажей - максимум 6 капель

12 этажей - максимум 8 капель

и т.п.

3 этажа - максимум 2 капли

Таким образом, для 99-этажного здания у вас будет максимум 66 капель. И это максимум. Скорее всего, у вас будет меньше капель. Да, и 66 - это тоже максимум для 100-этажного дома. Вам нужно было бы всего 66 капель, если бы пол перерыва был 98 или 97. Если бы пол перерыва был 100, вы бы использовали 34 падения.

Даже если вы сказали, что это не имеет значения, для этого, вероятно, потребуется наименьшее количество ходьбы, и вам не нужно знать, насколько высоко здание.

Отчасти проблема в том, как вы определяете эффективность. Является ли более «эффективным» всегда иметь раствор в количестве менее чем x капель, или более эффективно иметь хороший шанс получить раствор в количестве капель y, где y <x, с оговоркой, что у вас может быть более x капель ?

Я лично не большой поклонник подобных вопросов-головоломок, я предпочитаю актуальные упражнения по программированию на собеседованиях.

Тем не менее, во-первых, это будет зависеть от того, могу ли я сказать, сломаны они или нет, с пола, на который я их бросаю. Я полагаю, что смогу.

Я бы поднялся на второй этаж, уронил первый шарик. Если бы он сломался, я бы попробовал первый этаж. Если бы это сломалось, я бы знал, что это не пол.

Если бы первый не сломался, я бы пошел на 4-й этаж и упал оттуда. Если он сломается, я спущусь вниз и возьму другой шарик, а затем упаду на 3-й этаж, сломавшись или нет, я бы знал, какой предел.

Если бы ни один из них не сломался, я бы взял оба и проделал то же самое, на этот раз начиная с 6-го этажа.

Таким образом, я могу пропустить любой второй этаж, пока не получу треснувший шарик.

Это было бы оптимизировано на случай, если мрамор сломается рано ... Я полагаю, что, вероятно, есть оптимальное количество этажей, которое я мог бы пропустить, чтобы получить максимальную отдачу от каждого пропуска ... но тогда, если один сломается, мне придется проверять каждый этаж индивидуально с первого этажа над последним известным этажом ... что, конечно, было бы неприятно, если бы я пропустил слишком много этажей (извините, я не собираюсь сейчас определять оптимальное решение).

В идеале мне нужен целый мешок шариков, затем я мог бы использовать алгоритм двоичного поиска и делить количество этажей пополам с каждым падением ... но тогда вопрос был не в этом, не так ли?

Я думаю, что реальный вопрос заключается в том, насколько точным вы хотите получить ответ. Потому что от этого действительно будет зависеть ваша эффективность.

Я собираюсь согласиться с Джастином, если вы хотите 100% точности на шариках, тогда, как только первый шарик сломается, вам придется подниматься на 1 этаж за раз с последнего известного «хорошего» этажа, пока вы не выясните, какой этаж является победитель." Можно даже добавить статистику и начать с 25 этажа вместо 50, чтобы в худшем случае было 24 вместо 49.

Если ваш ответ может быть плюс или минус этаж или два, возможно, есть некоторые оптимизации.

Во-вторых, ходьба вверх / вниз по лестнице влияет на вашу эффективность? В этом случае всегда бросайте оба шарика и поднимайте оба шарика при каждом движении вверх / вниз.

Бросьте первый шарик на этаж 10, 20, 30 и т. Д., Пока он не сломается, затем прыгните обратно на последний известный хороший этаж и начните сбрасывать с него шарики по одному этажу за раз. В худшем случае 99 - это Magic Floor, и вы всегда можете найти его в 19 каплях или меньше.

Первое, что я бы сделал, это использовал мертвый простой алгоритм, который начинается с этажа 1, сбрасывает мрамор по одному этажу за раз, пока он не достигнет 100 или мрамор не расколется.

Тогда я бы спросил, зачем мне тратить время на оптимизацию, пока кто-то не покажет, что это будет проблемой. Слишком часто люди зацикливаются на поиске идеального сложного алгоритма, тогда как гораздо более простой решает проблему. Другими словами, не оптимизируйте вещи, пока это не понадобится.

Это может быть вопрос с подвохом, чтобы понять, относитесь ли вы к тем людям, которые могут сделать гору из кротового холма.

Эта проблема рассмотрена в задаче 6.5 из книги « Cracking the Coding Interview (5th) », решения которой резюмированы следующим образом:

Наблюдение:

Независимо от того, как мы отбрасываем Marble1, Marble2 должен выполнять линейный поиск. Например, если Marble1 прорывается между 10 и 15 этажами, мы должны проверить каждый этаж между Marble2.


Подход:

Первая попытка: предположим, мы уронили мрамор с 10 этажа, затем с 20,…

  • В первом Мрамор ломается при первом падении (Этаж 10), тогда у нас есть не более 10 капель.
  • Если первый мрамор разбивается на последней капле (этаж 100), то всего у нас будет не более 19 капель (этажи с 1 по 100, затем с 91 по 99).
  • Это неплохо, но все, о чем мы думаем, - это наихудший случай. Мы должны сделать некоторую «балансировку нагрузки», чтобы сделать эти два случая более равномерными.

Цель: создать систему сброса Marble1, чтобы максимальное количество требуемых падений было постоянным, независимо от того, ломается ли Marble1 при первом или последнем падении.

  1. Идеально сбалансированная система - это система, в которой капли Marble1 + Drops of Marble2 всегда одинаковы, независимо от того, где Marble1 сломался.
  2. Для этого, поскольку каждая капля Marble1 делает еще один шаг, Marble2 разрешается на один шаг меньше.
  3. Следовательно, мы должны уменьшать количество шагов, потенциально требуемых Marble2, на одну каплю каждый раз. Например, если Marble1 падает на этаж 20, а затем на этаж 30, Marble2 потенциально должен сделать 9 шагов. Когда мы снова отбрасываем Marble1, мы должны уменьшить количество возможных шагов Marble2 до 8, например, мы должны сбросить Marble1 на 39 этаже.
  4. Поэтому мы знаем, что Marble1 должен начинаться с этажа X, затем подниматься на X-1 этажа, затем на X-2,…, пока не дойдет до 100.
  5. Решить относительно X + (X-1) + (X-2) +… + 1 = 100. X (X + 1) / 2 = 100 -> X = 14

Мы идем на 14-й этаж, затем на 27, затем на 39,… Это занимает максимум 14 шагов.


Код и расширение: