Как вычислить наименьшего общего предка во времени NlogN, используя динамическое программирование на python

Это домашнее задание.

Входные данные: словарь списков, где каждый ключ является узлом, а значение - списком родителей узла. Пустой список означает, что узел является корнем.

{'1': ['3'], '2': ['3'], '4': ['5'], '3': ['5'], '6': ['7'], '8': ['7'], '7': ['9'], '5':['9'], '9':[]}

Вывод: словарь словарей, где каждый ключ - это узел i, а значение - это словарь, где каждый ключ - это узел j, а значение - это наименьший общий предок. Это сделано для всех узлов.

{'1': {'1': {'1'}, '9': {'9'}, '5': {'5'}, '3': {'3'}, '2': {'3'}, '4': {'5'}, '7': {'9'}, '6': {'9'}, '8': {'9'}}, '2': {'9': {'9'}, '5': {'5'}, '3': {'3'}, '1': {'3'}, '2': {'2'}, '4': {'5'}, '7': {'9'}, '6': {'9'}, '8': {'9'}}, '4': {'9': {'9'}, '5': {'5'}, '3': {'5'}, '1': {'5'}, '2': {'5'}, '4': {'4'}, '7': {'9'}, '6': {'9'}, '8': {'9'}}, '3': {'9': {'9'}, '5': {'5'}, '3': {'3'}, '2': {'3'}, '4': {'5'}, '7': {'9'}, '6': {'9'}, '8': {'9'}, '1': {'3'}}, '6': {'9': {'9'}, '5': {'9'}, '3': {'9'}, '1': {'9'}, '2': {'9'}, '4': {'9'}, '6': {'6'}, '7': {'7'}, '8': {'7'}}, '8': {'9': {'9'}, '5': {'9'}, '3': {'9'}, '1': {'9'}, '2': {'9'}, '4': {'9'}, '7': {'7'}, '6': {'7'}, '8': {'8'}}, '7': {'9': {'9'}, '5': {'9'}, '3': {'9'}, '1': {'9'}, '2': {'9'}, '4': {'9'}, '7': {'7'}, '8': {'7'}, '6': {'7'}}, '5': {'9': {'9'}, '5': {'5'}, '3': {'5'}, '2': {'5'}, '4': {'5'}, '7': {'9'}, '6': {'9'}, '8': {'9'}, '1': {'5'}}, '9': {'9': {'9'}, '5': {'9'}, '3': {'9'}, '2': {'9'}, '4': {'9'}, '7': {'9'}, '6': {'9'}, '8': {'9'}, '1': {'9'}}}

Алгоритм, который мы используем, должен быть алгоритмом динамического программирования, поэтому после небольшого исследования я обнаружил, что это можно сделать с временной сложностью NlogN, используя предварительный предварительный расчет разреженной таблицы для каждого 2-го предка узла i. Затем следует проверка, чтобы увидеть, находятся ли узел i и узел j на одном уровне, а если нет, то сделать их равными, если узлы i и j равны, то мы закончили, но если нет, то нам нужно найти x так, что x-й родитель узла i совпадает с x-м родительским узлом j. Поэтому, чтобы сделать это, я знаю, что должен найти наибольшее значение k (которое является разницей между глубинами двух узлов), чтобы 2^k-й родитель i и j отличался, а затем обновить i и j, чтобы они стали этими родителями., Мы продолжаем до тех пор, пока i и j не окажутся на одном уровне (k = 0), а затем мы узнаем, что узлы i и j находятся чуть ниже LCA, поэтому мы можем просто взять в качестве ответа родителя любого узла.

Теперь моя проблема в том, что... Я понимаю алгоритм, и я видел и прочитал множество учебных пособий с кодом /puesdocode о том, как это сделать, и я до сих пор не могу реализовать это в Python. До сих пор я был в состоянии только вычислить разреженную матрицу (что, честно говоря, я не совсем уверен, что это правильно), но я не знаю, как вычислить глубину каждого узла, чтобы продолжить. Я надеюсь, что кто-то может найти время, чтобы провести меня по алгоритму.

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

def preprocess(p=p):
    P = [[-1 for i in range(0, len(p) + 1)] for j in range(0, len(p) + 1)]
    for i in range(1, len(p) + 1):
        P[i][0] = p[str(i)]
        if P[i][0] == []:
            P[i][0] = [str(i)]
    for j in range(1, len(p) + 1):
        if (1 << j) < len(p):
            for i in range(1, len(p) + 1):
                if P[i][j-1] != -1:
                    inside = int(P[i][j-1][0])
                    P[i][j] = P[inside][j-1]
    return 

РЕДАКТИРОВАТЬ: Может быть полезно добавить, у меня на самом деле нет опыта программирования хе. Я био-майор, который по глупости решил пройти курс обучения вне своей стихии.

0 ответов

Другие вопросы по тегам