Как бы вы спроектировали структуры данных для очень большой социальной сети, такой как Facebook или Linkedln? Опишите, как бы вы разработали алгоритм, чтобы показать кратчайший путь между двумя людьми (например, Me-> Bob-> Susan-> Jason-> You).
Спросил в: Google Интервью
Хороший способ решить эту проблему — сначала снять некоторые ограничения и решить их для этой ситуации.
Случай 1: упростить проблему (не учитывая миллионы людей)
Мы можем построить график, рассматривая каждого человека как узел и позволяя ребру между двумя узлами указывать, что два пользователя являются друзьями. Если мы хотим найти путь между двумя людьми, мы начинаем с одного человека и делаем простой поиск в ширину . В качестве альтернативы, мы можем выполнить двунаправленный поиск в ширину. Это означает, что нужно выполнить два поиска в ширину, один из источника и один из пункта назначения. Когда поиски сталкиваются, мы знаем, что нашли путь.
Почему поиск в глубину не работает хорошо? Во -первых, поиск в глубину будет просто найти путь. Это не обязательно найти кратчайший путь. Во-вторых, даже если бы мы просто нуждались в каком-либо пути, это было бы очень неэффективно. У двух пользователей может быть только одна степень разделения, но он может искать миллионы узлов в своих «поддеревьях», прежде чем найдет это относительно непосредственное соединение.
В реализации мы будем использовать два класса, чтобы помочь нам. BFSData содержит данные, необходимые для поиска в ширину, такие как хеш-таблица isVisited и очередь toVisit. PathNode представляет путь, который мы ищем, сохраняя каждого человека и предыдущий узел, который мы посетили в этом пути.
Основная логика в Java приведена ниже
|
Как быстро это решение выше BFS?
Предположим, что у каждого человека есть k друзей, а у Source S и Destination D есть общий друг C.
1. Традиционный поиск в ширину от S до D: мы проходим примерно k + k * k узлов: каждый из k друзей S, а затем каждый из их k друзей.
2. Двунаправленный поиск в ширину: мы проходим 2k узлов: каждый из k друзей S и каждый из k друзей D. Конечно, 2k намного меньше, чем k + k * k.
3. Обобщая это к пути длины q, мы имеем это:
3.1 BFS: O (k q )
3.2 Двунаправленная BFS: 0 (k q / 2 + k q / 2 ), что равно 0 (k q / 2 )
Если мы представим путь, подобный A-> B-> C-> D-> E, где у каждого человека есть 100 друзей, это большая разница. BFS потребует просмотра 100 миллионов (100 4 ) узлов. Двунаправленная BFS потребует просмотра только 20 000 узлов (2 x 100 2 ).
Случай 2: справиться с миллионами пользователей
Для этих многих пользователей мы не можем хранить все наши данные на одной машине. Это означает, что наша простая структура данных Person сверху не совсем работает — наши друзья могут жить не на той же машине, что и мы. Вместо этого мы можем заменить наш список друзей списком их идентификаторов и перейти следующим образом:
1: для каждого идентификатора друга: int machine index = getMachineIDForUser (person_ID);
2: Перейти к машине #machine_index
3: На этой машине выполните: Person friend = getPersonWithID (person_ID);
Код ниже описывает этот процесс. Мы определили класс Server, который содержит список всех машин, и класс Machine, который представляет одну машину. Оба класса имеют хеш-таблицы для эффективного поиска данных.
Основная логика в Java приведена ниже->
|
Ниже приведены некоторые оптимизации и дополнительные вопросы.
Оптимизация: уменьшить количество скачков машины
Прыжки с одной машины на другую обходятся дорого. Вместо того, чтобы случайно прыгать с машины на машину с каждым другом, попробуйте выполнить пакетные прыжки — например, если пять моих друзей живут на одной машине, я должен искать их все сразу.
Оптимизация: умное разделение людей и машин
Люди гораздо чаще дружат с людьми, которые живут в той же стране, что и они. Вместо того, чтобы случайным образом распределять людей по машинам, попробуйте разделить их по странам, городам, штатам и т. Д. Это уменьшит количество прыжков.
Вопрос: Поиск в ширину обычно требует «пометки» узла как посещенного. Как ты это делаешь в этом случае?
Обычно в BFS мы отмечаем узел как посещенный, устанавливая флаг посещения в его классе узла. Здесь мы не хотим этого делать. Возможно одновременное выполнение нескольких поисков, поэтому плохая идея — просто отредактировать наши данные.
Вместо этого мы могли бы имитировать разметку узлов с помощью хеш-таблицы, чтобы найти идентификатор узла и определить, был ли он посещен.
Другие дополнительные вопросы:
1. В реальном мире серверы выходят из строя. Как это влияет на вас?
2. Как вы можете воспользоваться кешированием?
3. Вы ищете до конца графика (бесконечно)? Как вы решаете, когда сдаться?
4. В реальной жизни некоторые люди имеют больше друзей друзей, чем другие, и поэтому с большей вероятностью проложат путь между вами и кем-то еще. Как вы могли бы использовать эти данные, чтобы выбрать, с чего начать обход?
Ссылка на эту статью
Ссылка на эту статью
Эта статья предоставлена г-ном Сомешем Авастхи . Если вы как GeeksforGeeks и хотели бы внести свой вклад, вы также можете написать статью с помощью contribute.geeksforgeeks.org или по почте статьи contribute@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.
Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.
Рекомендуемые посты:
- API социальной сети
- Почему структуры данных и алгоритмы важны для изучения?
- Как легко стать хорошим специалистом по структурам данных и алгоритмам?
- 10 лучших алгоритмов и структур данных для конкурентного программирования
- Живые классы для структур данных и алгоритмов: курс подготовки к интервью
- Правильное использование социальных сетей
- Социальная инженерия — искусство виртуальной эксплуатации
- Конфиденциальность и безопасность в социальных сетях
- Футуристическое решение для конфиденциальности и безопасности в социальных сетях
- Facebook API | Set-2
- Facebook API | Set-4
- Facebook API | Set-3
- Facebook API | Set-1
- Разница между Data Scientist, Data Engineer, Data Analyst
- Почему бы вам не взломать Facebook!
0.00 (0%) 0 votes