Найти отметку времени с учетом K лучших кандидатов

Поэтому мне задали странную инверсию задачи о K лучших кандидатов. Обычная проблема заключается в следующем.

Учитывая список «голосов», которые представляют собой кортежи временных меток и кандидатов, как показано ниже:

(111111, Clinton)
(111111, Bush)
...

Возвратите лучших K кандидатов с наибольшим количеством голосов.

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

В конце концов вы возвращаете кучу.

Но в конце меня спросили: учитывая список из K кандидатов, вернуть временную метку, которая соответствует этим K лучшим кандидатам. Я не уверен, правильно ли я помню вопрос на 100%, потому что это должно было быть либо первое появление этих K кандидатов как лучших, либо мне был дан подсчет их голосов.


person SpaceDandy    schedule 27.05.2018    source источник
comment
Каков твой вопрос?   -  person Taslim Oseni    schedule 28.05.2018
comment
Как найти отметку времени, данную K лучшим кандидатам?   -  person SpaceDandy    schedule 29.05.2018


Ответы (1)


Если я все понимаю, votes — это список кортежей для голосования, состоящих из кандидатов, за которых голосуют, и временной метки происходящего голосования. currTime — это временная метка всех голосов за эту временную метку до нее. topCandidates — кандидаты с наибольшим количеством голосов в currTime.

Ваш первый вопрос дает вам votes и currTime, ожидается, что вы вернете topCandidates. Ваш второй вопрос дает вам votes и topCandidates, и ожидается, что вы вернете currTime.

Сосредоточившись на втором вопросе, я бы сделал карту, где ключи — это метка времени, а значения — все голоса, происходящие в данный момент. Также я бы создал еще одну карту, где ключом является кандидат, а значением является количество голосов, которые они имеют на данный момент. Я бы прошел первую карту в порядке возрастания временной метки первой карты, получил все голоса, которые были отданы в временной метке, и увеличил значения второй карты их кандидатом (ключом). Прежде чем переходить к следующей отметке времени, я бы создал список кандидатов, за которых проголосовало больше всего, с данными на второй карте. Если этот список соответствует topCandidates, то последняя пройденная временная метка будет currTime.

Чтобы закодировать это в python:

from collections import Counter, defaultdict
def findCurrTime(votes, topCandidates):
    if not (votes and topCandidates):
        return -1
    votesAtTime = defaultdict(list)
    candidatePoll = Counter()
    k = len(topCandidates)
    for time, candidate in votes: # votes = [(time0, candidate0), ...]
        votesAtTime[time].append(candidate)
    for ts in votesAtTime:
        candidatePoll += Counter(voteAtTime[ts])
        if list(map(lambda pair: pair[0],candidatePoll.most_common(k))) == topCandidates:
            return ts
    # if topCandidates cannot be created from these votes:
    return -1

Есть некоторые предположения, которые я сделал (надеюсь, вы спросили о них своего интервьюера). Я предположил, что порядок topCandidates имеет значение, с которым будет работать Counter.most_common, хотя он не будет обрабатывать кандидатов с количеством голосов.

Временная сложность равна O(t * n * log(k)), где t — количество меток времени, n — количество голосов, а k — размер topCandidates. Это связано с тем, что Counter.most_common выглядит как O(n *log(k)) и может запускаться t раз. Однако есть определенно более эффективные ответы.

person user2361174    schedule 27.05.2018
comment
Разве вы не предполагаете, что метки времени, возвращаемые как ключи к вашему dict, отсортированы? Также наиболее распространенным здесь является klog(k). Так почему же не O(t*n*(klogk))? Также не будет ли шага для сравнения того, что чаще всего возвращается в topCandidates, что равно k ^ 2 или, по крайней мере, с некоторым дополнительным пространством 2k? Спасибо за этот общий подход, хотя - person SpaceDandy; 28.05.2018
comment
Ключи в словарях просматриваются в том порядке, в котором они были созданы, поэтому, пока временные метки отсортированы в votes (о чем вы должны спросить своего интервьюера), временные метки должны проходиться в порядке возрастания. Most_common равен O(n*log(k)), потому что мы ищем первые k значений из списка, которые могут быть n (на последней метке времени). Подобно тому, как обход половины квадратной матрицы составляет O (n ^ 2). Сравнение most_common и topCandidates — это просто сравнение двух списков вместе, что составляет O(n), что значительно меньше времени most_common. - person user2361174; 28.05.2018