Как научиться решать задачи в программировании
Перейти к содержимому

Как научиться решать задачи в программировании

10 шагов по решению задач в программировании

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

1. Прочитайте условия задачи как минимум трижды (или хотя бы столько раз, сколько вам будет удобно)

Вы не сможете решить задачу, если не поймёте её. Есть разница между задачей и задачей, которую, как вам кажется, вы решаете. Можно прочитать первые несколько строк, а насчёт остального выстроить предположения, поскольку всё выглядит похожим на то, с чем вы сталкивались раньше. Даже если вы делаете популярную игру наподобие Виселицы, удостоверьтесь, что прочитали все её правила, пусть даже вы играли в неё раньше.

Иногда можно попробовать объяснить задачу другу и посмотреть, поймёт ли он ваше объяснение. Вы же не хотите пройти половину пути и обнаружить, что неправильно поняли требования. Так что лучше потратить в начале больше времени, чтобы всё прояснить. Чем лучше поймёте задачу, тем легче будет её решить.

Допустим, мы создаём простую функцию selectEvenNumbers , которая берёт массив чисел и возвращает массив evenNumbers с одними лишь чётными числами. Если чётных чисел в исходном массиве нет, то массив evenNumbers возвращается пустым.

Какие вопросы можно себе задать:

  • Как компьютер может сказать, что число является чётным? Разделить на 2 и проверить, чтобы результат получился целым.
  • Что я передаю этой функции? Массив.
  • Что содержит этот массив? Одно или несколько чисел.
  • Какие типы данных у элементов массива? Числа.
  • Какова цель этой функции? Что я возвращаю в конце её выполнения? Цель — получить все чётные числа и вернуть их в массиве. Если нет чётных чисел, то массив возвращается пустым.

2. Пройдите по задаче вручную как минимум с тремя наборами данных

Возьмите лист бумаги и пройдите по задаче вручную. Выберите не менее трёх наборов данных для проверки. Выберите предельно допустимые и крайние случаи.

Предельно допустимые случаи: проблема или ситуация, возникающая за пределами нормальных параметров функционирования. Например, когда одновременно несколько переменных или состояний среды имеют экстремальные значения, даже если каждый из параметров находится в своём специфическом диапазоне.

Крайние случаи: проблемы или ситуации, возникающие только при экстремальных (минимальных или максимальных) значениях параметров функционирования.

Вот, к примеру, несколько наборов данных для использования:

[1]
[1, 2]
[1, 2, 3, 4, 5, 6]
[-200.25]
[-800.1, 2000, 3.1, -1000.25, 42, 600]

Когда только начинаешь, то зачастую пренебрегаешь какими-то шагами. Поскольку наш мозг уже знаком с чётными числами, то можно просто посмотреть на набор чисел и сразу передать в массив 2, 4, 6 и так далее, не думая о том, как наш мозг выбирает конкретные числа. Если вы замечаете это за собой, то лучше взять большой набор данных, чтобы помешать мозгу решать задачу, просто глядя на числа. Это поможет придерживаться настоящего алгоритма.

Давайте пройдём по массиву [1]

  1. Смотрим на единственный элемент массива [1] .
  2. Определяем, является ли он чётным. Не является.
  3. Замечаем, что других элементов в массиве нет.
  4. Определяем, что здесь нет чётных чисел.
  5. Возвращаем пустой массив.
  1. Смотрим на первый элемент массива [1, 2]
  2. Это 1 .
  3. Определяем, является ли он чётным. Не является.
  4. Смотрим на следующий элемент.
  5. Это 2 .
  6. Определяем, является ли он чётным. Является.
  7. Создаём массив evenNumbers и добавляем в него 2 .
  8. Замечаем, что других элементов в массиве нет.
  9. Возвращаем массив evenNumbers — [2] .

3. Упрощайте и оптимизируйте свой алгоритм

Поищите подходящие паттерны, может быть, что-то удастся обобщить. Подумайте, можно ли уменьшить количество шагов.

  1. Создадим функцию selectEvenNumbers .
  2. Создадим новый пустой массив evenNumbers для хранения чётных чисел.
  3. Проходим по каждому элементу массива [1, 2] .
  4. Находим первый элемент.
  5. Делим его на 2 и определяем, чётный ли он. Если да, то прибавляем к evenNumbers .
  6. Находим следующий элемент.
  7. Повторяем шаг №4.
  8. Повторяем шаги №5 и №4, пока не кончатся элементы в массиве.
  9. Возвращаем массив evenNumbers вне зависимости от того, есть ли в нём что-то.
  1. Доказываем истинность для n = 1 , n = 2 , .
  2. Предполагаем, что будет истинно для n = k .
  3. Доказываем истинность для n = k + 1 .

4. Пишите псевдокод

После проработки основных шагов напишите псевдокод, который можно перевести в настоящий код. Это поможет определить структуру кода, да и вообще облегчит его написание. Пишите псевдокод построчно. Это можно делать на бумаге или в виде комментариев в редакторе. Если вы только начинаете и считаете, что пустой экран выглядит жутковато или отвлекает, то лучше писать на бумаге.

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

Применительно к нашему случаю есть много разных вариантов. Например, можно использовать filter , но ради простоты примера воспользуемся простым циклом for (однако при последующем рефакторинге мы ещё столкнёмся с filter ).

Вот пример псевдокода, в основном состоящего из слов:

А вот псевдокод, в котором слов гораздо меньше:

Главное, писать код построчно и понимать логику каждой строки.

Вернитесь к задаче, чтобы удостовериться, что вы на правильном пути.

5. Преобразуйте псевдокод в нормальный код и отладьте его

Когда ваш псевдокод будет готов, преобразуйте каждую строку в реальный код на вашем языке. Здесь мы воспользуемся JavaScript.

Если вы писали на бумаге, то перенесите всё в редактор в виде комментариев, а затем замените каждую строку.

Теперь вызовите функцию и дайте ей некоторые из ранее использованных наборов данных. Так можно проверить, возвращает ли код нужный результат. Также можете написать тесты для проверки соответствия выходных данных ожидаемому результату.

После каждой переменной или строки можно использовать console.log() . Это поможет проверить, ведут ли себя значения и код так, как ожидается, прежде чем двигаться дальше. Таким образом вы выловите любые проблемы, не зайдя слишком далеко. Вот пример того, какие значения можно проверить при начале работы.

Ниже приведён код, полученный после обработки каждой строки псевдокода. Символы // обозначают строки из псевдокода. Жирным выделен реальный код на JavaScript.

Уберём псевдокод, чтобы не путаться.

Иногда разработчики-новички настолько увлекаются синтаксисом, что им трудно идти дальше. Помните, что со временем вам будет проще соблюдать синтаксис, и нет ничего стыдного в том, чтобы потом при написании кода обращаться к справочным материалам для корректного соблюдения синтаксиса.

6. Упрощайте и оптимизируйте код

Возможно, вы заметили, что упрощение и оптимизация — это повторяющиеся темы.

Эдсгер Дейкстра, нидерландский учёный и один из первопроходцев в ряде областей информатики

В нашем примере одним из путей оптимизации будет фильтрация элементов в массиве посредством возвращения нового массива с помощью filter . В этом случае нам не нужно определять переменную evenNumbers , потому что filter вернёт новый массив с копиями элементов, которые соответствуют фильтру. При этом исходный массив не изменится. Также нам не нужно использовать цикл for . filter пройдёт по каждому элементу, и если вернёт true, то элемент попадёт в массив, а если false , то будет пропущен.

Может потребоваться несколько итераций упрощения и оптимизации кода, по мере того как вы будете находить новые способы.

Задавайте себе такие вопросы:

  • Каковы цели упрощения и оптимизации? Цели зависят от принятого в вашей команде стиля или ваших личных предпочтений. Вы пытаетесь максимально уплотнить код? Или вы хотите сделать его более читабельным? В таком случае вы можете добавить отдельные строки с определением переменной или вычислением чего-либо, а не пытаться всё сделать в одной строке.
  • Как ещё можно сделать код более читабельным?
  • Можно ли ещё уменьшить количество шагов?
  • Есть ли переменные или функции, которые не нужны или не используются?
  • Какие-то шаги повторяются? Посмотрите, можно ли определить в другой функции.
  • Существуют ли более эффективные способы обработки крайних случаев?

Джеральд Сассман и Гарольд Абельсон, авторы “Structure and Interpretation of Computer Programs”

7. Отлаживайте

Этот шаг необходимо выполнять в ходе всего процесса. Сквозная отладка поможет раньше выловить любые ошибки синтаксиса или недостатки логики. Воспользуйтесь преимуществами своего IDE (Integrated Development Environment) и отладчика. При обнаружении бага рекомендуется просматривать код построчно, стараясь найти неожиданные вещи. Несколько советов:

  • Читайте, что пишется в сообщения об ошибках в консоли. Иногда в них указываются номера строк для проверки. Это даст вам исходную точку для поисков, хотя иногда проблемы могут скрываться в других строках.
  • Комментируйте блоки кода или строки, а также выходные данные, чтобы быстро подмечать поведение кода. При необходимости код можно всегда раскомментировать.
  • Используйте другие образцы данных, если возникают непредусмотренные сценарии.
  • Сохраняйте разные версии файла, если применяете другие подходы. Не стоит терять наработанное, если захочется откатиться к прежнему решению!

Брайан Керниган, профессор информатики в Принстонском университете

8. Пишите полезные комментарии

Через месяц вы можете и не вспомнить, что означает каждая строка кода. А тот, кто будет работать с вашим кодом, вообще этого не знает. Поэтому важно писать полезные комментарии, чтобы избежать проблем и сэкономить впоследствии время, когда придётся снова вернуться к этому коду.

Избегайте таких комментариев:

// Это массив. Итерируем его.
// Это переменная.

Старайтесь писать короткие, высокоуровневые комментарии, которые помогут понять, что тут происходит, если это не очевидно. Это пригодится при решении сложных задач, вы сможете быстро понять, что делает конкретная функция, и почему. Благодаря использованию понятных комментариев и имён переменных и функций вы (и другие люди) сможете понять:

  • Для чего этот код?
  • Что он делает?

9. Получайте отзывы посредством ревизии кода

Получайте отзывы от коллег, руководителей и других разработчиков. Читайте Stack Overflow. Смотрите, как другие решали аналогичные задачи и учитесь у них. Нередко бывает несколько способов решения задачи. Узнайте, что они собой представляют, и вам будет быстрее и проще приходить к ним самостоятельно.

Дядя Боб Мартин, программный инженер и соавтор манифеста Agile

10. Практикуйтесь, практикуйтесь, практикуйтесь

Даже опытные разработчики постоянно практикуются и учатся. Если вы получили полезный отклик, внедрите его. Снова решите задачу, или аналогичные задачи. Заставляйте себя. С каждой решённой задачей вы становитесь лучше как разработчик. Радуйтесь каждому успеху и не забывайте, как много вы уже прошли. Помните, что программирование, как и любая деятельность, со временем будет даваться всё проще и легче.

Как решать задачи на программирование

Перевод статьи «How to Solve Coding Problems with a Simple Four Step Method».

Photo by Cécile Brasseur on Unsplash

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

Ни в одном туториале из тех, по которым я училась программированию, не рассказывалось о решении задач. А мне определенно нужно было овладеть этим искусством: от этого зависела вся моя будущая карьера разработчика. И я немедленно взялась за поиски.

То, что я нашла, было не просто подходом, а бесценной стратегией. Это был проверенный временем алгоритм действий в четыре шага, который по какой-то причине остался незамеченным в сфере разработки.

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

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

Универсальный подход к решению задач

Этот метод изложен в книге «Как решать задачу» Дьёрдя Пойа. Первое издание вышло еще в 1945 году, было продано больше миллиона экземпляров. (На русском языке книга публиковалась как пособие для учителей еще в 1959 году. — Прим. перев.).

Метод Пойа используют многие программисты, от профессоров информатики (см. курс «Intro to CS» на Udacity, который ведет профессор Дэвид Эванс) до преподавателей современной веб-разработки вроде Кольта Стила.

Давайте пройдемся по решению простой задачи на программирование с применением метода Пойа. Это позволит увидеть работу метода на практике и в результате лучше разобраться в нем. Для примера будем использовать язык JavaScript.

Создайте функцию, которая будет складывать два числа и возвращать их сумму.

Вот четыре шага по решению любой задачи:

  1. Понять задачу.
  2. Разработать план.
  3. Осуществить план.
  4. Оглянуться назад.

«Во-первых, мы должны понять задачу; мы должны ясно видеть, что в ней является искомым. Во-вторых, мы должны усмотреть, как связаны друг с другом различные элементы задачи, как неизвестное связано с данными. Это необходимо, чтобы получить представление о решении, чтобы составить план. В-третьих, мы осуществляем наш план. В-четвертых, оглядываясь назад на полученное решение, мы вновь изучаем и анализируем его», — «Как решать задачу», 1959 г.

Давайте сделаем первый шаг.

Photo by Dimitri Houtteman on Unsplash

Шаг 1: понять задачу

Когда вы на собеседовании получаете задачу на программирование, возникает соблазн тут же приступить к написанию кода. Этому искушению трудно противостоять, особенно, если время ограничено.

Тем не менее, постарайтесь удержаться. Прежде чем приступать к решению задачи, убедитесь, что вы хорошо поняли, что от вас требуется.

Прочтите текст задачи. Можно даже читать вслух, если это поможет вам притормозить.

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

Этот первый шаг жизненно важен. Мы часто не уделяем достаточного количества времени на то, чтобы разобраться в постановке задачи. А если вы не до конца понимаете задачу, вам будет куда труднее ее решить.

Чтобы помочь себе разобраться, спросите себя:

Каковы здесь входящие данные?

Какого рода input-ы следует ожидать? В нашем примере это аргументы, принимаемые функцией.

Читая текст задачи, мы понимаем, что входящими данными будут числа. Если подходить к делу более скрупулезно, мы можем спросить:

  • всегда ли будет только два числа?
  • что будет, если функция получит в качестве входящих данных три числа?

Эти вопросы мы можем задать интервьюеру или поискать ответ в описании задачи. (К задаче может прилагаться примечание типа «Исходите из того, что в функцию всегда будут передаваться только два числа». Конечно, это сразу все прояснит).

Можно задаться и другими вопросами. Всегда ли входящими данными будут числа? Что должна делать функция, если получит в качестве аргументов «a» и «b»? Уточните, всегда ли input будет числовым.

В качестве варианта — можно записать вероятные входящие данные в комментарии к коду, чтобы иметь представление о том, как они должны выглядеть.

Далее следует спросить себя:

Каковы должны быть результаты?

Что функция будет возвращать? В нашем случае это должно быть оно число — сумма двух чисел, переданных в качестве аргументов. Убедитесь, что вы хорошо понимаете, каким должен быть output.

Придумайте простые примеры

Разобравшись в сути задачи и зная вероятные input-ы и output-ы, можно начать работать над конкретными примерами.

Примеры также могут использоваться для тестирования вашего решения. На техническом собеседовании или при подготовке к нему на сайтах вроде Codewars или HackerRank используются специальные редакторы. Большинство из них содержат уже готовые примеры или test cases. Несмотря на это, написание собственных примеров может помочь вам упрочить понимание задачи.

Начните с написания одного-двух простых примеров.

Давайте вернемся к нашей складывающей функции. Назовем ее «add».

Каким может быть input? Ну, допустим, таким:

Каким будет результат при таких входящих данных? Записать это можно так:

Это показывает, что наша функция принимает в качестве input 2 и 3, а как output возвращает 5.

Photo by Jason Leung on Unsplash

Придумайте сложные примеры

Продумывая более сложные примеры, вы можете уделить время поиску крайних случаев, которые стоит учесть.

Например, что будет, если наши входящие данные будут не числами, а строками? Что, если мы получим в качестве аргументов две строки, например, add(‘a’, ‘b’)?

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

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

Если вы не на собеседовании, а просто решаете задачу, в ней может быть обозначено, что должно происходить при вводе невалидных данных.

Например, в задаче может говориться «При отсутствии input-а верните undefined». В таком случае можно написать комментарий:

В нашем случае мы будем исходить из того, что input всегда будет числовым. Но в общем всегда лучше подумать о крайних случаях.

Профессор информатики Эванс советует писать т. н. безопасный код. Всегда думайте о том, что может пойти не по плану и как защитить свой код от возможных ошибок.

Прежде чем перейти ко второму шагу, давайте кратко повторим, что нужно сделать на первом шаге:

  • прочитать задачу
  • выяснить, какими будут входящие данные
  • выяснить, каким должен быть результат
  • создать простые примеры, затем — более сложные.

Шаг 2: разработать план решения задачи

Далее нужно составить план того, как вы, собственно, собираетесь решать задачу. Придумав план, запишите его в виде псевдокода.

Псевдокод — это изложенные простым языком шаги алгоритма. Иными словами, это пошаговый план решения задачи.

Опишите каждый этап решения. Если задача сложная, этапов может быть много. Если говорить о нашей задаче, мы можем написать:

Теперь у вас есть четырехэтапный план решения задачи.

Для более сложных задач профессор Эванс советует: «Полагайтесь на то, как задачи решаются людьми». То есть, забудьте на мгновение о том, как задачу может решить код, и подумайте о том, как ее решали бы вы — человек. Это может помочь вам более четко увидеть нужные шаги.

Photo by Chewy on Unsplash

3. Шаг 3: осуществить план (решить задачу!)

Следующий шаг — собственно решение задачи. Руководствуясь псевдокодом, напишите настоящий код.

Профессор Эванс рекомендует сфокусироваться на простом, механическом решении. Чем проще и легче ваше решение, тем вероятнее, что вы напишете код правильно.

Если взять наш псевдокод, мы можем написать следующее:

Помните, что не следует преждевременно оптимизировать код. Написав решение, вы можете подумать, что ваш код неэффективный, и захотеть его улучшить. Но для начала создайте простое, механическое решение.

Что, если вы не можете решить задачу полностью? Например, если вы так и не нашли решения для какой-то ее части? Кольт Стил советует в таких ситуациях игнорировать эту сложную часть. Сконцентрируйтесь на всем остальном — том, что вы уже можете написать. Когда напишете, возвращайтесь к части, которая вызвала у вас затруднения.

Шаг 4: оглянуться назад

Когда у вас на руках будет готовое рабочее решение, подумайте, как его можно улучшить. На этом этапе можно провести рефакторинг и преобразовать свое решение в более эффективное.

Просматривая свою работу, вы можете задать себе несколько вопросов:

  • Можно ли получить этот результат как-то иначе? Какие еще подходы есть?
  • Понятно ли это решение с первого взгляда?
  • Можно ли использовать результат или метод для какой-то другой задачи?
  • Можно ли улучшить производительность решения?
  • Не приходят ли вам на ум какие-то способы рефакторинга для этого решения?
  • Как эту задачу решают другие люди?

Возвращаясь к нашему коду, мы можем сделать его более лаконичным, если удалим нашу переменную и используем имплицитный return:

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

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

Когда я практиковалась в решении задач, я практически всегда смотрела и чужие решения, которые часто были элегантнее и эффективнее моих.

Итоги

В этой статье мы рассмотрели четырехэтапную стратегию решения задач на программирование. Давайте повторим:

  • Шаг 1: понять задачу
  • Шаг2: создать пошаговый план решения
  • Шаг 3: реализовать план и написать код решения
  • Шаг 4: оглянуться назад и по возможности улучшить решение.

Применение этого подхода очень помогло мне при прохождении технических собеседований, да и вообще в моей работе.

Если вы не чувствуете себя уверенно, решая задачи, помните, что умение решать задачи — это навык. Чем больше практики, тем лучше вам это будет удаваться.

Грокаем алгоритмы: Гайд по алгоритмам для тех, кому сложно решать задачи

Грокаем алгоритмы: Гайд по алгоритмам для тех, кому сложно решать задачи главное изображение

Грокать алгоритмы или не грокать? Что делать, если вам не хочется решать сто задач к вашему следующему собеседованию?

Часть меня ненавидит технические собеседования, в первую очередь из-за того, что мне нужно повторять много материала. Кроме того, в процессе самого собеседования мне часто приходится предлагать какое-то особенное решение, а не то, которое я бы выбрал в своей будничной практике.

Несмотря на это, я люблю алгоритмы и люблю решать задачки по программированию. Для меня это веселое времяпровождение и хорошая тренировка для мозга. Учитывая все это, хочу рассказать вам о моей собственной технике подготовки к собеседованиям, которая намного интереснее и волнительнее, чем обычная подготовка.

Коротко расскажу о себе, чтобы вы убедились в моей экспертности. Я программирую уже 20 лет, за это время я много раз менял место работы. Всего я прошел около 30 воронок найма — больше 120 собеседований. Плюс к этому у меня есть опыт с той стороны баррикад: я провел около 300 технических собеседований и больше 200 собеседований по системному дизайну.

Где мы грокаем алгоритмы

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

Самая большая проблема LeetCode в том, что сайту не хватает продуманной системы обучения. У него много разных задач, в которых легко потеряться. Сколько нужно таких задач, чтобы подготовиться к собеседованию? Я бы предпочел двигаться по продуманной программе, в конце которой я смогу ощутить уверенность в собственных знаниях. Но системы нет, а я ленивый, и вообще — не хочу решать 500+ задач.

Одно из популярных решений для этой проблемы — решать задачи, которые относятся к одной структуре данных (например, прорешать несколько задач с деревьями). Какая-то система обучения появляется, но это решение меня все равно не устраивает. Например, что делать, если задачу можно решить при помощи разных структур данных?

Какую систему обучения придумал я

Я бы предпочел такую систему, в которой задачи распределены по паттернам, а не по структурам данных. Мои любимые паттерны — скользящее окно, нахождение цикла и топологическая сортировка. Когда я научился пользоваться этими методами, я стал решать незнакомые задачи по аналогии с задачами, которые решал до этого. Благодаря этому весь процесс подготовки к собеседованиям стал более интересным и веселым. Ну и конечно же, более систематичным.

Я обнаружил 25 паттернов, которые лежат в основе решения большинства задач. Думаю, эти паттерны помогут кому угодно показывать на собеседованиях красивые и элегантные решения. Вся фишка этих паттернов в том, что понимая один из них, вы научитесь решать сразу несколько задач, десятки задач.

Самые распространенные паттерны для решения задач

Читайте также: Это снова я, резиновая уточка: что такое метод Фейнмана и почему с его помощью так просто изучать программирование

Метод скользящего окна

Контекст: Мы используем этот метод, когда у нас есть входные данные с заданным размером окна.

Задачи для этого паттерна:

Метод двух указателей

Контекст: Мы используем два указателя, чтобы перебрать все входные данные. Обычно два указателя движутся в противоположных направлениях с фиксированным интервалом.

Задачи для этого паттерна:

Нахождение цикла

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

Задачи для этого паттерна:

Интервальное слияние

Контекст: Этот метод применяют, если есть пересекающиеся интервалы. Например, на этом изображении мы видим, что интервалы a и b могут пересекаться шестью разными способами:

Задачи для этого паттерна:

Цикличная сортировка

Контекст: Если входные данные лежат в заданном интервале, используйте цикличную сортировку.

Задачи для этого паттерна:

In-place Reversal для LinkedList

Техника: Эта техника описывает эффективный способ перевернуть связи между узлами в LinkedList (класс Java). Часто мы ограничены in-place, то есть мы должны использовать исходные узлы.

Задачи для этого паттерна:

Поиск в ширину

Контекст: Это метод для решения задач с деревьями.

Задачи для этого паттерна:

Поиск в глубину

Контекст: Тот же, что для предыдущего метода.

Задачи для этого паттерна:

Двоичная куча

Контекст: Во многих задачах у нас есть набор элементов, который можно разделить на две части. Тогда мы могли бы выяснить, какой элемент является наименьшим в первой куче и какой является наибольшим во второй куче.

Задачи для этого паттерна:

Подмножества

Контекст: Если задача требует перестановки или комбинаций элементов, используйте подмножества.

Задачи для этого паттерна:

Усовершенствованный бинарный поиск

Контекст: Эта техника использует логический оператор для наиболее эффективного поиска элементов.

Задачи для этого паттерна:

Наибольшее K элементов

Контекст: Эта техника используется, чтобы найти наибольший/наименьший или наиболее часто встречающийся набор k-элементов в коллекции.

Задачи для этого паттерна:

Читайте также: Как решить задачу, если непонятно, с чего вообще начать: советы от Хекслета

K-образное слияние

Контекст: Используйте эту технику, если у вас есть список отсортированных массивов.

Задачи для этого паттерна:

Рюкзак 0-1

Контекст: Этот паттерн используют для задач на оптимизацию. Используйте эту технику, чтобы выбирать элементы, которые дают максимум выгоды в данном наборе ограничений по вместимости. Учитывая то, что каждый элемент может быть выбран лишь единожды.

Задачи для этого паттерна:

Неограниченный рюкзак

Контекст: То же самое, что в предыдущем паттерне, но только каждый элемент может быть выбран повторно сколько угодно раз.

Задачи для этого паттерна:

Числа Фибоначчи

Контекст: Как очевидно из названия, это паттерн для чисел Фибоначчи. Это последовательность, в которой каждое последующее число равно сумме двух предыдущих чисел.

Задачи для этого паттерна:

Наибольшая последовательность — палиндром

Контекст: Имеется в виду задача, которая может быть использована как для последовательности, так и для строк. По сути это задача на оптимизацию.

Задачи для этого паттерна:

Наибольшая общая подстрока

Контекст: Как понятно из названия, это паттерн для работы со строками или другими последовательностями, а также для работы с наборами строк или последовательностей.

Задачи для этого паттерна:

Чтение префиксного дерева

Контекст: Это специфичная для структуры данных техника, с помощью которой читают или создают префиксное дерево.

Задачи для этого паттерна:

Острова в матрице

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

Задачи для этого паттерна:

Путь проб и ошибок

Контекст: Этот паттерн подойдет для того, чтобы пройтись по массиву в поисках подходящего под требования элемента.

Задачи для этого паттерна:

Система непересекающихся множеств

Контекст: Если данные раскиданы по непересекающимся множествам, то они решаются одним и тем же способом.

Задачи для этого паттерна:

Поиск уникального маршрута

Контекст: Этот паттерн подойдет для прохождения по любому многомерному массиву.

Задачи для этого паттерна:

Никогда не останавливайтесь: В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *