Научись думать как программист и проследи за всем процессом мышления и работы, когда опытный программист решает задачу по программированию и оптимизации кода.
Статья объясняет, как разбиение сложных задач на части, распознавание шаблонов и системный подход помогут вам мыслить, как программист. Независимо от вашего уровня, этот подход может улучшить как навыки решения проблем, которые необходимы в программировании, а также логическое мышление.
Введение
Для того чтобы поддерживать остроту своих навыков программирования, время от времени я решаю задачи на LeetCode. Это здорово, потому что этот сайт постоянно развивается, у него дружелюбный интерфейс, ты можешь выбирать задачи на интересующие тебя темы, и там есть отличное сообщество, у которого можно многому научиться.
Мне всегда было интересно узнать, что происходит в голове у программистов, когда они решают задачи. Как это происходит на самом деле? Поскольку я не смог найти подходящего материала на эту тему, я решил сам написать о том, как это происходило у меня.
Эта публикация на форуме сообщества LeetCode вызвала довольно бурную реакцию и получила сотни голосов “за”, поэтому я делюсь этим опытом и здесь, в блоге.
Задача
Вот сама задача:
Учитывая массив целых чисел nums, отсортируй массив в возрастающем порядке, основываясь на частоте значений. Если несколько значений имеют одинаковую частоту, отсортируй их в порядке убывания. Верни отсортированный массив.
Пример 1:
Input: nums = [1,1,2,2,2,3] Output: [3,1,1,2,2,2] Объяснение: “3” имеет частоту 1, “1” имеет частоту 2, а “2” имеет частоту 3.
Начало
Раннее воскресное утро, музыка из Spotify, горячий кофе, любимая командная строка, отличное настроение… Задание из списка задач “Решить Позже”.
Итак, мне нужно подсчитать частоту встречаемости каждого из уникальных значений… Первая идея - использовать Counter. Это возвращает тип объекта collection:
Теперь мне нужно отсортировать эти значения, следуя требованиям в описании. У объекта Counter нет атрибута sort, а sorted будет сортировать только значения, а не частоты. Погуглив различные варианты, нашел вот этот вопрос на StackOverflow со множеством полезных ответов. Читаем… Пробуем более простой объект:
>>>r=Counter(nums).most_common()
Это возвращает список кортежей, где первое число - значение, а второе - его частота. Могу ли я отсортировать его в этой же команде? Идем и читаем официальную документацию. Неа, не сортируется в самой команде, более того: “Элементы с одинаковым количеством упорядочиваются в порядке первой встречи”. Хорошо, давай отсортируем напрямую, сначала по значениям в порядке убывания, затем по частотам в порядке возрастания.
Выглядит многообещающе. Теперь я хочу расширить эти кортежи до одного списка… Все еще просматриваю ответы на тот же самый вопрос. Вспомнил, что я могу расширить кортеж и получить из него каждое число, используя вот это:
>>>a,b=(3,2)>>>a3>>>b2
тогда я смогу повторять каждое значение по числу его частоты вот так:
>>>[3]*2[3,3]
Ага. Теперь мне нужен пустой список, чтобы объединить все эти кортежи в один список:
Результат: Время выполнения: 52 мс, быстрее, чем 63,30% других решений на Python 3 для сортировки массива по возрастающей частоте.
Использование памяти: 14,2 МБ, меньше, чем у 58,20% других решений на Python 3 для сортировки массива по возрастающей частоте.
Не самый лучший вариант, но задача решена.
Улучшаем
Теперь пришло время для очередной забавы - смогу ли я сделать решение в одну строку или оптимизировать решение каким-либо другим способом? Это уже просто баловство + тренировка + удовольствие :)
Смотрим на сортировку строк… Могу ли я отсортировать их за один раз? Да! Итак, сначала мы сортируем по значениям в обратном порядке (-x[0]), а затем по их частотам (x[1]) в прямом порядке.
>>>r.sort(key=lambdax:(x[1],-x[0]))
По сути, это та же операция, что и выше, но теперь закодированная в одну строку. Люблю Python :) Та же логика применима к части расширения кортежа, и это позволяет нам сэкономить еще одну строку:
t=[]foriinr:t+=([i[0]]*i[1])
И тут я подумал - если я могу сортировать по значению и его частоте, зачем мне нужен промежуточный список? Могу ли я отсортировать исходный список тем же способом?! Давай посмотрим…
Вуаля! Это так здорово. Но x.sort делает это in-place, т.е. прямо в самом исходном объекте, а мне нужно вернуть новый объект… Поэтому мне нужно изменить операцию на sorted:
Время выполнения: 44 мс, быстрее, чем 95,07% других решений на Python 3 для сортировки массива по возрастающей частоте.
Использование памяти: 14,3 МБ, меньше, чем у 58,20% других решений на Python 3 для сортировки массива по возрастающей частоте.
Заключение
Решение задач по программированию требует сочетания знаний, опыта и творческих навыков решения проблем. Понимая ход мыслей и приемы, используемые опытными программистами, ты сможешь улучшить свою способность разбивать сложный код на части, выявлять и преодолевать препятствия.
С практикой и упорством каждый может стать опытным программистом и преуспеть в своей области. Не забывай всегда оставаться любознательным и продолжать учиться, ведь технологии и языки программирования постоянно развиваются.