@kaliboba

Почему мой код считается медленным?

Добрый день, решил учить алгоритмы, зашёл на leetcode, нашёл задачу (ссылка внизу), написал код, однако на 20 тесте он выдаёт огромный массив и пишет, что время вышло за лимит
Вопрос, что в нём не так

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        d = {i: nums.count(i) for i in nums}
        s = sorted(d.items(), key= lambda x:x[1],     reverse = True)
        result = [s[i][0] for i in range(k)]
        return result


https://leetcode.com/problems/top-k-frequent-eleme...
  • Вопрос задан
  • 342 просмотра
Пригласить эксперта
Ответы на вопрос 5
sergey-gornostaev
@sergey-gornostaev Куратор тега Python
Седой и строгий
Изучение алгоритмов стоит начинать с чтения соответствующего учебника, как минимум станет известна методика оценки сложности алгоритма. И лучше это делать после того, как прочитан учебник по языку и документация по его стандартной библиотеке.
Ответ написан
Комментировать
wataru
@wataru Куратор тега Алгоритмы
Разработчик на С++, экс-олимпиадник.
Ваш алгоритм работает за O(n^2). Вы для каждого числа в массиве считатете, сколько раз оно туда входит проходя по массиву через nums.count(i). Оптимальное же решение работает O(n). Надо в хеш-таблице подсчитать, сколько раз каждое число встречается, потом через алгоритм QuickSelect выбрать k-ый c конца элемент.

Ну, или можно за O(n log n) отсортировать массив и потом за один проход подсчитать сколько раз каждое число встречается. Дальше можно второй раз отсортировать по количеству вхождений и выдать k-ый элемент. Это решение тоже пройдет.
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
d = {i: nums.count(i) for i in nums}
Здесь вы для каждого значения в списке полностью просматриваете весь список. В результате получаете сложность O(n2). Таким образом, объём вычислений у вас увеличивается квадратично от увеличения размера списка (список вырос в 2 раза, объём в 4, список в 100 раз, объём в 10000 раз). Соответственно, увеличивается и время, необходимое на вычисления.
Ответ написан
Комментировать
@AlexSku
не буду отвечать из-за модератора
Так первая же строчка неэффективная:
for i in nums - один проход по массиву
nums.count(i) - для каждого прохода ещё один проход.
Т.е. если 1e6, то вы делаете 1e12 проходов.
2 и 3 строки уже быстрые.
Ответ написан
Комментировать
@Bright144
попробуй это
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        return sorted(set(nums), key=nums.count, reverse=True)[:k]

leetcode у нас заблокирован. По теории так скорость выполнение кода должен значительно вырасти(почти 2раза).
Самый быстрый код это тот код когда решаешь всю задачу за один цикл(это мое мнение).
У тебя тут:
цикл для d;
цикл для s;
цикл для result;
В итоге 2 лишних циклов.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы