1. Python / Говнокод #4317

    −94

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    # -*- coding: utf-8 -*-
    
    # На входе: не пустой b-массив
    # На выходе: словарь из 1-ого элемента {самый часто встречающийся элемент:количество}
    
    # 1. Сначала составляем словарь, потом ищем максимум и возвращаем
    def Freq1(b):
      assert len(b) > 0
      d = {}
      for x in b: # Пробегаем в цикле исходный массив
        d[x] = d[x] + 1 if d.has_key(x) else 1 # Если ключ уже есть, прибавляем 1, если нет, записываем 1
      v = max(d, key=d.get) # v ключ из словаря соответствующий максимальному значению
      return {v:d[v]} # Возвращаем ответ
    
    # 2. Ищем максимум прямо при составлении словаря
    def Freq2(b):
      d = {}
      m, i = 0, 0 # Максимальная частота и индекс в словаре
      for x in b: # Пробегаем в цикле исходный массив
        d[x] = d[x] + 1 if d.has_key(x) else 1 # Если ключ уже есть, прибавляем 1, если нет, записываем 1
        if d[x] > m:
          m, i = d[x], x # Запоминаем максимум и его индекс
      return {i:m}
    
    # 3. Без использования словаря (сложность квадратичная - "тупой метод")
    def Freq3(b):
      m, i = 0, 0 # Максимальная частота и соответствующее ему значение
      for x in b:
        c = b.count(x) # Сколько раз встречается x в массиве b?
        if c > m:
          m, i = c, x
      return {i:m}
    
    # Проверка (примитивный unit-тест)
    def Check(inData, expected):
      assert Freq1(inData) == expected
      assert Freq2(inData) == expected
      assert Freq3(inData) == expected
    
    Check(["banana", "banana", "apple", "banana", "banana", "apple", "onion"], {'banana': 4})
    Check([2, 3, 9, 3, 6, 6], {3: 2})
    Check([True, True, True, False, False, True], {True: 4})

    Самый часто встречающийся элемент в массиве (3 способа).
    Везде сплошной говнокод. Как ПРАВИЛЬНО найти самый часто встречающийся элемент в массиве?
    Наверное, можно ещё отсортировать массив и пробежать по нему храня текущий элемент и количество и обновляя соответствующие переменные?

    Запостил: denis, 09 Октября 2010

    Комментарии (15) RSS

    • 1й вариант со словарём самый оптимальный, если у вас нет ограничений на использование памяти и т.д.
      >>Наверное, можно ещё отсортировать массив и пробежать по нему храня текущий элемент и количество и обновляя соответствующие переменные?
      сортировка требует времени
      Ответить
      • Просто мне кажется, что я считаю зачем-то количество всех элементов. Может можно как-то отсекать редко встречающиеся элементы.
        Например, строить сбалансированное бинарное дерево прямо при проходе массива, в узлах будет значение:количество?
        У меня плохо с алгоритмами :)
        Ответить
        • >Например, строить сбалансированное бинарное дерево прямо при проходе массива, в узлах будет значение:количество?
          зачем переусложнять? "За деревьями леса не видно" ©

          вам надо задачу решить или на девушку произвести впечатление уровнем владения алгоритмами и технологиями? так вроде как не этим впечатляют испокон веку :)
          Ответить
          • >вам надо задачу решить или на девушку произвести впечатление уровнем владения алгоритмами и технологиями? так вроде как не этим впечатляют испокон веку :)

            во-во поэтому советую ебануть теоркатом: катаморфизмы, анаморфизмы, хиломорфизмы, параморфизмы наконец.
            Ответить
          • Мне нужно написать самое простое решение задачи, которое удовлетворило бы её препода.
            В прошлый раз в задаче поиска элемента и вставки в массив её препод сказал, что бинарный поиск ещё кое-как подходит :)
            Я написал 5 вариантов: http://stden.livejournal.com/397391.html
            Ответить
            • Вставку в отсортированный сырой массив без разницы как делать, ибо эта операция обречена на O(N) независимо от алгоритма. Если вообще такое понадобилось делать - значит
              1) массив совсем небольшой, и проще и быстрее всего прогнать итерацию insertion sort.
              2) структура данных выбрана неверно, и нужно её менять целиком; например, использовать сортированный multiset.
              Ответить
      • Также, может есть встроенная функция чтобы это сделать?
        Ответить
    • Сессия ж нескоро, неужто уже с курсачами зажимают?
      Ответить
      • Да, это я помогаю знакомой девушке. Просто я ей пишу как бы я сделал (я сам только начинаю программировать на Python) и мне постоянно кажется, что мои решения не python'овские. В Java я себя чувствую намного уверенней. Я привык копаться в больших Java-проектах и уже примерно знаю что там и как делается.
        Ответить
        • Тематика сайта - смехотворный код, а не взаимная помощь и не pastebin. Чтобы это понять, не нужно знание Python'а, нужно знание русского, чтобы прочитать, что написано в шапке страницы, и логика, чтобы, просмотрев хотя бы несколько страниц, убедиться в справедливости написанного. Я не модератор, чтобы указывать, да. Тут вообще модераторов нет. Но Вы не первый, кто приходит сюда за помощью, и смотреть на оффтопик лично я уже подустал. Без обид. Найдёте кусок идиотского кода на той же Jav'е - постите сюда, посмеёмся вместе, опять же.
          Ответить
      • Например, я почти не использую генераторы и лямбда-выражения, потому что ещё просто не чувствую когда их правильно применять (т.е. есть некоторые очевидные случаи - генерация последовательности с заданными свойствами, это понятно), а вот общее правило??
        Ответить
    • from collections import Counter
      dict((Counter(b).most_common()[0],))
      Ответить
    • > Как ПРАВИЛЬНО найти самый часто встречающийся элемент в массиве?

      Если это лаба, то пофигу, лишь бы не квадратично.

      Если бы это нужно сделать один раз в реальной жизни, я бы сделал так:
      1) строим хэш таблицу со счётчиками за амортизированное O(N)
      2) преобразуем её в массив пар за O(N)
      3) строим max heap по частотам за O(log N)
      4) вершина хипа - ответ за O(1)
      Такой алгоритм работает за амортизированное O(N). Я почти уверен, что питоний Counter, упомянутый выше, примерно так и работает.

      Если операция частая и/или может затрагивать подмассивы, гуглите Range Mode Query.
      Ответить

    Добавить комментарий