<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>ru</language>
    <title>Задачи повышенной сложности</title>
    <description>Если вы уже опытный специалист по решению необычных задач — попробуйте разобраться с головоломками из этой рубрики.</description>
    <link>https://tproger.ru/tag/expert-problems</link>
    <atom:link href="https://tproger.ru/tag/expert-problems/feed" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Fri, 02 Oct 2026 23:21:04 GMT</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>12</sy:updateFrequency>
    <image>
      <title>Задачи повышенной сложности</title>
      <link>https://tproger.ru</link>
      <url>https://tproger.ru/apple-touch-icon.png</url>
    </image>
    <item>
      <title>Не только для собеседований: как LeetCode и аналоги помогают новичкам в программировании</title>
      <link>https://tproger.ru/articles/ne-tolko-dlya-sobesedovanij--kak-leetcode-i-analogi-pomogayut-novichkam-v-programmirovanii</link>
      <comments>https://tproger.ru/articles/ne-tolko-dlya-sobesedovanij--kak-leetcode-i-analogi-pomogayut-novichkam-v-programmirovanii?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Диана Тажетдинова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/ne-tolko-dlya-sobesedovanij--kak-leetcode-i-analogi-pomogayut-novichkam-v-programmirovanii</guid>
      <description><![CDATA[<p>Алгоритмические задачи развивают логику, структурное мышление и помогают на собеседованиях и в работе. Узнайте, с чего начать, как избежать выгорания и сохранить мотивацию.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/ne-tolko-dlya-sobesedovanij--kak-leetcode-i-analogi-pomogayut-novichkam-v-programmirovanii">Не только для собеседований: как LeetCode и аналоги помогают новичкам в программировании</a>»</p>]]></description>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Практика]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Навыки]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 21 Aug 2025 14:00:04 GMT</pubDate>
      <content:encoded><![CDATA[<p>Многие новички боятся алгоритмических задач. Кажется, что это бустер для кандидатов в Google, которые решают графы на доске маркером, а не для тех, кто только осваивает циклы. Но опыт разработчиков показывает: даже простые задачи могут заметно улучшить качество кода.</p><p>Мы поговорили с экспертами и попросили их поделиться задачами, которые помогут прокачать логику и навыки работы с данными. Заодно узнали, зачем вообще новичку браться за алгоритмы. Решения оставим в комментариях. Не подглядывайте сразу, а сначала попробуйте свои силы.</p><h2>Зачем вообще решать алгоритмические задачи</h2><p>Алгоритмы в начале карьеры нужны не всем. Эксперты честно говорят, что практика на реальных маленьких проектах может дать больше пользы. Но выкидывать алгоритмы из своего обучающего трека точно не стоит, и вот почему.</p><p>Разработчик Валерий Жила говорит, что на алгоритмы можно смотреть по-разному:</p><blockquote>С одной стороны, алгоритмы новичкам не нужны — пусть лучше берутся за практические проекты, даже если это просто репозиторий на GitHub, который можно запустить на локалхосте. С другой — это как классическая литература или высшая математика. Напрямую в работе может не пригодиться, но здорово прокачивает мозги и помогает найти общий язык с другими разработчиками.</blockquote><p>А Константин Шибков, senior Java-разработчик в СДЭК, автор <a href="https://t.me/three_monitors">канала «Три монитора»</a>, вспоминает, что задачи стали для него тренировочным залом для мозгов:</p><blockquote>Когда я был новичком, знаний для полноценного приложения не хватало, а тренироваться хотелось. LeetCode показал мне, когда использовать массивы, деревья, словари, множества, и как эффективно обходить или искать данные. А просмотр чужих решений после своего помогал находить новые приёмы.</blockquote><p>Даже если вы не мечтаете прямо сейчас попасть в Google или Amazon, алгоритмические задачи — это отличная тренировка. Они помогут:</p><ul><li>развить логику и выстроить чёткий план решения,</li><li>натренировать декомпозицию — разбивку сложного на простое,</li><li>мыслить в терминах массивов, графов и деревьев.</li></ul><p>В бигтехе эти навыки проверяют особо тщательно: Яндекс, OZON и другие компании любят устраивать отдельные алгоритмические сессии. Бонусом вы будете готовы и к ним.</p><figure><img src="https://media.tproger.ru/user-uploads/114509/2025-08-15/90914bb0-f966-49e6-aa1e-3c0990809dbb.jpeg" alt="" /></figure><h2>Простые задачи — лучший вход</h2><p>Начинать сразу со сложного или среднего уровня — это как пытаться пробежать марафон без единой тренировки. Эксперты однозначно советуют начинать с чего-нибудь лёгкого. Чем проще задача, тем выше шанс её довести до конца.</p><blockquote>Например, Merge Two Sorted Lists — простая задача, которая учит работать с указателями. Разобравшись, можно попробовать Merge k Sorted Lists — это более сложная задача с тем же базовым подходом.</blockquote><blockquote>Нужно в первую очередь освоить базовые структуры данных. Научиться видеть в них инструмент с понятной и простой функцией, как лопата или молоток.</blockquote><p>Почему простые задачи действительно приносят пользу:</p><ul><li>вы быстро получаете результат и мотивацию продолжать,</li><li>можно сосредоточиться на логике, а не на дебаге сложных условий;</li><li>легче отрабатывать приёмы и паттерны, которые потом повторяются в сложных задачах.</li></ul><h2>Где искать задачи для практики</h2><p>Загляните на специальные онлайн-сервисы для практики алгоритмического программирования. Вот список популярных в русскоязычной среде сайтов:</p><ul><li><a href="https://leetcode.com/">LeetCode</a> — мировой лидер, база задач от простых до сложных для подготовки к интервью</li><li><a href="https://codeforces.com/">Codeforces</a> — сообщество для соревнований и обучения</li><li><a href="https://coderun.yandex.ru/">CodeRun</a> — российская платформа с задачами на алгоритмы и регулярными контестами</li><li><a href="https://acm.timus.ru/">Timus Online Judge</a> — портал с архивом олимпиадных задач, востребованный у студентов и олимпиадников</li><li><a href="https://adventofcode.com/">Advent of Code</a> — ежегодный онлайн-марафон задач в формате адвент-календаря, стилизованный под приключения</li><li><a href="https://www.codewars.com/">Codewars</a> — геймифицированная платформа с заданиями по разным языкам и уровням сложности</li></ul><blockquote>Как-то раз я завалил экзамен по алгоритмам в университете, будучи уверенным, что предмет — элементарный. Взялся за материалы, LeetCode, Advent of Code, Codewars и пару месяцев плотно ими занимался. Решал по 5−10 задач в день. Экзамен я пересдал на отлично. На последующих собеседованиях уже получалось интуитивно нащупывать решения.</blockquote><figure><img src="https://media.tproger.ru/user-uploads/114509/2025-08-15/3383b7e0-2e3c-4157-9f9e-ac37f079a031.png" alt="" /><figcaption>Фишки LeetCode: большое международное комьюнити, 14 языков программирования и возможность получить оффер от IT-гигантов</figcaption></figure><h2>Что решают разработчики, чтобы держать мозг в тонусе</h2><p>Попросили экспертов выбрать задачи, которые они сами считают полезными для развития алгоритмического мышления.</p><p>Валерий Жила:</p><ol><li><a href="https://leetcode.com/problems/two-sum/">Two Sum</a> — найти два числа в массиве, сумма которых равна заданному значению. Чему учит: работать с хэш-таблицами и быстро находить соответствия. Базовый паттерн, который часто встречается в других задачах.</li><li><a href="https://leetcode.com/problems/number-of-islands/">Number of Islands</a> — посчитать количество связных компонент на карте. Чему учит: обходить граф DFS/BFS, думать в терминах связности элементов.</li><li><a href="https://leetcode.com/problems/decode-string/">Decode String</a> — декодировать строку с вложенными структурами. Чему учит: использовать стек, вложенные циклы и парсинг данных.</li></ol><p>Совет: «Если сухой LeetCode наскучил, попробуйте Advent of Code».</p><p>Константин Шибков:</p><ol><li><a href="https://leetcode.com/problems/maximize-distance-to-closest-person/">Maximize Distance to Closest Person</a> — выбрать место в ряду, чтобы максимизировать расстояние до ближайшего соседа. Чему учит: работать с краевыми случаями, искать оптимальную позицию по условию.</li><li><a href="https://leetcode.com/problems/merge-two-sorted-lists/">Merge Two Sorted Lists</a> — объединить два отсортированных списка в один. Чему учит: работать с указателями и аккуратно обрабатывать данные в упорядоченных структурах.</li><li><a href="https://leetcode.com/problems/move-zeroes/">Move Zeroes</a> — переместить все нули в конец массива, сохранив порядок остальных элементов. Чему учит: оптимизировать алгоритм без создания дополнительных структур.</li><li><a href="https://leetcode.com/problems/partition-to-k-equal-sum-subsets/">Partition to K Equal Sum Subsets</a> — разделить массив на K подмножеств с равной суммой элементов. Чему учит: использовать поиск с возвратом, оптимизировать перебор.</li></ol><p>Никита Дубко, старший руководитель продуктов Яндекс Контеста, автор <a href="http://t.me/mefody_dev">канала mefody.dev</a></p><ol><li><a href="https://coderun.yandex.ru/problem/new-year-fruits-2/">Мандарины и апельсины 2.0</a> — выбрать n ящиков так, чтобы в них оказалось не менее половины всех мандаринов и апельсинов. Чему учит: использовать свойства возрастающих последовательностей, минимизировать количество проходов по данным и находить решение без полного перебора.</li><li><a href="https://coderun.yandex.ru/problem/cha_cha/">Ча-ча-ча</a> — определить итоговую оценку по набору буквенных оценок с ограничением, что итог не может быть более чем на балл выше худшей. Чему учит: работать со строками и символами в ASCII/UTF-8, а также применять решение в лоб, когда оно эффективно.</li></ol><p>Совет: «Тренируйтесь не только решать, но и объяснять, почему ваш алгоритм работает и укладывается в ограничения. Этот навык ценят на собеседованиях».</p><h2>Как не сломаться на старте: выгорание и ошибки новичков</h2><p>Практика алгоритмов должна прокачивать мозг, а не выматывать его. Но у многих новичков энтузиазм быстро сменяется усталостью — чаще всего из-за завышенных ожиданий и неверной стратегии.</p><p>Главные ловушки:</p><ul><li>Гонка на износ. План «100 задач за месяц» звучит амбициозно, но в реальности превращается в марафон без подготовки.</li><li>Залипание на одной задаче. Если вы часами бьётесь над решением, азарт сменяется усталостью.</li><li>Кажется, что все остальные ушли далеко вперед. Вы видите только чужие успехи, но не видите их ошибки.</li><li>Синтаксическая ловушка. Новички пытаются угадать код, вместо того чтобы проработать логику на бумаге.</li><li>Держать всё в голове. Легко потеряться в деталях, если не набросать план на бумаге.</li></ul><blockquote>Если задача по зубам, решение само скомпилируется в голове. Иногда полезно просто отойти, попить чаю или лечь спать.</blockquote><p>Что советуют эксперты:</p><ul><li>Решайте по одной задаче в день, как утреннюю разминку для мозга.</li><li>Чередуйте лёгкие и средние задачи, чтобы тренироваться в комфортном темпе, но с небольшим вызовом. Так вы будете расти без ощущения, что тонете.</li><li>Если за час решение не приходит, то посмотрите разбор без кода, а затем напишите свой вариант.</li><li>Отмечайте, какой приём вы отработали — это даёт чувство прогресса.</li><li>Записывайте решение пошагово. Даже опытные разработчики часто начинают с блокнота.</li></ul><blockquote>Я получал удовольствие, когда решал задачу своим способом, проходил все тесты и потом видел в чужом коде приёмы, о которых даже не думал.</blockquote><h2>Как продолжать развиваться</h2><p>Когда лёгкий уровень перестанет пугать, и вы будете уверенно разбираться в массивах, строках и базовых структурах данных, двигайтесь дальше. Как в спорте: если всегда работать с одной гантелью, прогресса не будет.</p><p>1. Освойте новые темы. Начните с самых популярных направлений, которые часто встречаются в реальной разработке и на собеседованиях:</p><ul><li>сортировки,</li><li>графы,</li><li>строковые алгоритмы,</li><li>деревья.</li></ul><p>2. Устройте себе челлендж. Например, «30 задач за 30 дней». Берите не количеством, а регулярностью. Можно чередовать дни по уровням сложности.</p><p>3. Используйте готовые подборки. Есть отличные списки от экспертов. Приведём лишь некоторые из них</p><ul><li><a href="https://seanprashad.com/leetcode-patterns/">LeetCode Patterns</a> — задачи сгруппированы по типам и темам;</li><li><a href="https://leetcode.com/problem-list/oizxjoit/">Blind 75</a> — 75 самых популярных задач для собеседований;</li><li><a href="https://www.geeksforgeeks.org/blogs/gfg160-160-days-of-problem-solving">GfG‑160</a> — 160 задач для тех, кто хочет по-настоящему прокачать алгоритмы</li></ul><p>4. Пробуйте альтернативные платформы. Чтобы не застревать в одном формате, чередуйте площадки. Разные интерфейсы и условия помогут смотреть на задачи с нескольких сторон.</p><figure><img src="https://media.tproger.ru/user-uploads/114509/2025-08-15/fafb8ef0-7b0e-4b0b-bf24-489d7ad426e7.jpeg" alt="" /></figure><blockquote>Однажды на работе мне нужно было распределить посылки по ячейкам постамата так, чтобы максимально эффективно использовать пространство. По сути, это была вариация задачи Partition to K Equal Sum Subsets: разложить элементы по контейнерам без перегруза. Я использовал поиск с возвратом и оптимизацию, которые до этого отрабатывал на алгоритмических задачах. Закрыл задачу быстрее, чем если бы разрабатывал всё с нуля. <br /><br />Но стоит учесть, что код на LeetCode отличается от того, что мы обычно пишем в прод. У нас на работе даже есть локальный мем «по-литкодовски», когда код — максимально короткий, без попытки быть понятным и простым. Главное для него — быть эффективным. Когда переносишь алгоритмы решения в реальный мир, нужно выделять алгоритм в изолированный класс или метод. Так вы сможете проверить его тестами и сделать более понятным для других.</blockquote><h2>Выводы</h2><ul><li>Алгоритмические задачи развивают логику, структурное мышление и умение разбивать проблему на шаги. Навыки пригодятся и на собеседованиях, и в реальной работе.</li><li>Начинать лучше с простых задач, чтобы закрепить основы и избежать выгорания.</li><li>Нужно научиться не только решать задачи, но и объяснять, почему алгоритм работает.</li><li>Ищите задачи на разных платформах, чтобы сохранить интерес и прокачивать навыки в разных форматах.</li><li>Лучше решать по одной задаче в день, чем десяток в выходные.</li><li>Не гонитесь за чужим темпом и чередуйте уровни сложности.</li><li>Личный опыт экспертов показывает, что алгоритмы могут спасти на экзамене и ускорить поиск рабочих решений.</li></ul><p>Читайте также:</p><p><a href="https://tproger.ru/articles/algoritm-dejkstry--kak-rabotaet-i-gde-ispolzuetsya">Алгоритм Дейкстры: как работает и где используется</a></p><p><a href="https://tproger.ru/articles/top-10-algoritmov--kotorye-realno-nuzhny-na-bekende">ТОП-15 алгоритмов, которые реально нужны на бэкенде</a></p><p><a href="https://tproger.ru/articles/chto-takoe-hew-tablicy-i-kak-ih-ispolzovat">Что такое хэш-таблицы и как их использовать</a></p><p><a href="https://tproger.ru/articles/kviz--kakoj-stek-tehnologij-tebe-podhodit-">Квиз: какой стек технологий тебе подходит?</a></p><p><a href="https://tproger.ru/articles/rabochij-plan--kak-izuchit-novyj-stek-za-3-mesyaca">Рабочий план: как изучить новый стек за 3 месяца</a></p>]]></content:encoded>
    </item>
    <item>
      <title>7 математических задач на LeetCode для продвинутых</title>
      <link>https://tproger.ru/articles/7-matematicheskih-zadach-na-leetcode-dlya-prodvinutyh</link>
      <comments>https://tproger.ru/articles/7-matematicheskih-zadach-na-leetcode-dlya-prodvinutyh?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Мария Кривоченко]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/7-matematicheskih-zadach-na-leetcode-dlya-prodvinutyh</guid>
      <description><![CDATA[<p>Собрали несколько математических задач высокого уровня сложности и добавили варианты решения на Python.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/7-matematicheskih-zadach-na-leetcode-dlya-prodvinutyh">7 математических задач на LeetCode для продвинутых</a>»</p>]]></description>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 26 Jan 2024 15:44:59 GMT</pubDate>
      <content:encoded><![CDATA[<p>LeetCode — одна из самых популярных платформ для решения задач по программированию и подготовки к техническим собеседованиям. Мы выбрали 7 математических задач уровня Medium и Hard и предлагаем вам проверить свои навыки.</p><p>У каждой задачи может быть несколько решений — на разных языках программирования. Мы предложили варианты на Python от участника сообщества.</p><h2>Игра в камни IX</h2><p>Алиса и Боб играют в камни. Они выстроили ряд из n камней, каждому из которых присвоили значение. То есть у них есть массив целых чисел stones, где stones[i] — значение i-го камня.</p><p>Алиса и Боб играют по очереди, Алиса ходит первой. На каждом ходу можно убрать любой камень из stones. Если сумма значений всех убранных камней делится на 3, участник проигрывает. Алиса также проигрывает, если камни заканчиваются.</p><p>Предполагая, что игроки выбрали оптимальные стратегии, верните true, если победит Алиса, и false, если победит Боб.</p><h2>Сколько существует способов достичь пункта назначения через k шагов</h2><p>Вы находитесь на бесконечной числовой оси на точке startPos, положение точки равно положительному целому числу. Цель — прийти к точке endPos, положение которой также равно положительному целому числу. За один шаг вы можете переместиться на одну позицию влево или вправо.</p><p>Вычислите, сколько способов достичь endPos существует, если нужно совершить k шагов (k также равно положительному целому числу)? Количество способов может быть большим, поэтому выведите значение в формате 10^9 + 7.</p><h2>Найдите палиндром определенной длины</h2><p><i>Палиндром — это число, которое читается одинаково справа налево и слева направо.</i></p><p>queries — массив целых чисел; intLength — положительное целое число. Определите массив answer, где answer[i] — либо меньший палиндром  queries[i], длина которого равна intLength либо -1, если такого палиндрома не существует.</p><h2>Сколько прямых линий нужно, чтобы построить диаграмму</h2><p>У вас есть двумерный массив целых чисел stockPrices. stockPrices[i] = [day_i, price_i] — цена акции в день i. Линейный график, отражающий динамику цен, создается из точек stockPrices[i], лежащих на плоскости XY, где ось X — день, а ось Y — цена. Один из таких графиков показан ниже:</p><figure><img src="https://media.tproger.ru/user-uploads/23823/2024-01-26/86a9a875-db15-4f13-ab86-ff33ac841440.png" alt="" /></figure><p>Найдите минимальное число линий, которое нужно, чтобы объединить все точки на плоскости и построить график.</p><h2>Сократить произведение диапазона целых чисел</h2><p>У вас есть два целых числа left и right, где left &lt;= right. Вычислите произведение всех целых чисел, входящих в диапазон [left, right]. Затем сократите произведение, выполнив следующие действия:</p><ul><li>уберите все нули в конце получившегося числа.</li></ul><ul><li>если в получившемся числе больше десяти цифр, представьте его в формате &lt;pre&gt;...&lt;suf&gt;, где &lt;pre&gt; — первые пять цифр, а &lt;suf&gt; — последние.</li></ul><ul><li>представьте получившееся число в виде строки &lt;pre&gt;...&lt;suf&gt;eC.</li></ul><h2>Почитайте число анаграмм</h2><p>У вас есть строка s, в которой находятся одно или несколько слов. Каждая пара слов разделена пробелом.</p><p>Строка t — анаграмма строки s, i-е слово строки t — может быть анаграммой только i-го слова строки s. Например, acb dfe — анаграмма abc def, а def cab и adc bef — нет.</p><p>Вычислите число анаграмм s. Их количество может быть большим, поэтому выведите значение в формате 10^9 + 7.</p><h2>Проверьте, реально ли добраться до точки</h2><p>Есть бесконечно большая сетка. Вы находитесь в точке (1, 1) и должны добраться до (targetX, targetY), используя определенное число шагов. targetX и  targetY — целые числа.</p><p>За один шаг вы можете переместиться из точки (x, y) в любую из следующих:</p><ul><li>(x, y – x);</li></ul><ul><li>(x – y, y);</li></ul><ul><li>(2 * x, y);</li></ul><ul><li>(x, 2 * y).</li></ul><p>Определите, можете ли вы добраться до (targetX, targetY) из (1, 1), верните true, если да, иначе верните false.</p>]]></content:encoded>
    </item>
    <item>
      <title>Сказ о том, как я за год решил более 600 leetcode задач</title>
      <link>https://tproger.ru/articles/skaz-o-tom--kak-ya-za-god-rewil-bolee-600-leetcode-zadach</link>
      <comments>https://tproger.ru/articles/skaz-o-tom--kak-ya-za-god-rewil-bolee-600-leetcode-zadach?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Suleiman Dibirov]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/skaz-o-tom--kak-ya-za-god-rewil-bolee-600-leetcode-zadach</guid>
      <description><![CDATA[<p>Личный опыт: как за год решить более 600 задач на LeetCode, пройти coding-интервью в Booking, Careem и Avito и перестать бояться алгоритмических задач. Советы по выбору языка, порядку тем и ресурсам.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/skaz-o-tom--kak-ya-za-god-rewil-bolee-600-leetcode-zadach">Сказ о том, как я за год решил более 600 leetcode задач</a>»</p>]]></description>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Для продолжающих]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 25 Jan 2024 12:23:08 GMT</pubDate>
      <content:encoded><![CDATA[<p>Хочу рассказать вам историю о том, как я начинал с уровня — «не могу решить даже 1 easy задачу из 10» до уровня — «могу решить каждую вторую medium задачу» и прошел несколько coding сессий в таких компаниях как Booking, Careem, Avito…Всем салют!</p><p>Началось все с того, что в конце 2022 года я твердо решил, что хочу устроиться в FAANG компанию, но для этого, как вы наверно все знаете, нужны знания алгоритмов и структур данных, коих у меня не было, потому что в обычной работе тебе не нужны heap, tree, disjoint set и другие структуры данных, поэтому начать пришлось практически с нуля.</p><p>Было очень тяжело, т.к. не знал с чего начинать, по какому принципу решать задачи, что важно, а что не очень, сколько нужно решить задач, чтоб чувствовать уверенность, получится ли вообще перейти на medium задачи, т.к. решение даже easy задач заводило в тупик, ниже постараюсь ответить на все эти вопросы.</p><p>Самое первое, что приходит в голову, когда хочешь начать решать задачи на литкоде — это открыть <a href="https://leetcode.com/problemset/all/">страницу с задачами</a> и начать решать их подряд, но это не очень хорошая идея, даже если вы применили фильтр easy, потому что очень много задач с пометкой easy очень сложно решить и это может сильно демотивировать, а то и понизить самооценку.</p><p>Начинать решать LeetCode нужно не подряд, а по темам: сначала array, hashmap, set — и только потом stack, tree, graphs.</p><p>Если задача не решается за 30–40 минут — смотрите разбор, изучайте решение и возвращайтесь к ней снова. Повторение — ключ к закреплению.</p><p>Python — лучший язык для LeetCode: лаконичный синтаксис и богатая стандартная библиотека (Counter, defaultdict, heapq) экономят время на интервью.</p><p>Уверенность при прохождении coding-интервью появляется примерно после 400–500 решённых задач; 600+ задач снимают страх полностью.</p><h2>Советы</h2><ol><li>Первый совет – обращайте внимание на процент Acceptance, чем этот процент больше, тем лучше, потому что это означает, что у многих людей получается решить эту задачу и есть вероятность, что и у вас получится.Также можете открыть study plan и попробовать решать задачи оттуда:<br /> – <a href="https://leetcode.com/studyplan/top-100-liked/">Топ 100 залайканных задач,</a> если много лайков, значит есть вероятность, что это не какая-то хитросплетеная задача, которая может понизить вашу оценку(есть много задач для которых нужны специфичные знания и это может быть неочевидно с первого взгляда)<br /> – <a href="https://leetcode.com/studyplan/top-interview-150/">Топ 150 задач для подготовки к интервью</a>, вероятность встретить эти задачи на интервью высока, но тут могут быть сложные задачи, которые трудно будет решить в начале пути<br /> – Как пишет leetcode, <a href="https://leetcode.com/studyplan/leetcode-75/">это “Must-do problem list for interview prep”</a>. Задачи в этих списках распределены на разные темы, решать нужно их следуя следующему совету.</li><li>Второй совет – начинайте с самых фундаментальных структур данных, таких как array(одномерный/двумерный), set, hashmap, они будут встречаться вам постоянно, к примеру, во многих задачах время выполнение можно улучшить добавив set или hashmap(но нужно учесть, что увеличится потребление памяти) и только после того как освоите их, можно начинать углубляться в другие структуры как stack, queue, linked list, tree, graphs.<br />На самом leetcode <a href="https://leetcode.com/explore/learn/">есть карточки, в которых дается объяснение структурам данных</a> и алгоритмам + задачи для закрепления этих тем, как и написано выше, начинайте с простых карточек – array, string и постепенно повышайте уровень, я несколько раз возвращался к карточкам, т.к. некоторые моменты порой были непонятны с первого раза, поэтому не думайте, что с вами что-то не так, если что-то непонятно, вернетесь потом и обнаружите, что уже понимаете это.<br /><a href="https://neetcode.io/roadmap">Тут есть roadmap с темами и задачами</a>, очень советую<br /><a href="https://www.techinterviewhandbook.org/grind75">Тут можно создать понедельный план</a> с применением различных фильтров<br /><a href="https://seanprashad.com/leetcode-patterns/">Список из 150 популярных задач</a>, разделенные на темы, сложность и компании</li><li>Третий совет – если не можете придумать оптимальное решение, начинайте с решения “в лоб”, как только получится, подумайте над тем, как это решение можно улучшить, может можно использовать какую-то структуру? может массив можно отсортировать? а что если использовать set или hashmap? можно ли использовать какой-то шаблон? Если ничего не помогает и вы уже потратили 20-40 минут, то смело открывайте решение задачи и изучайте это решение, как только вы это сделали, закройте решение и попробуйте заново решить(таких итераций может быть несколько, это нормально!), если после нескольких итераций не получилось, просто перепечатайте решение(я неоднократно так делал), НО не забудьте через время вернуться к этой задаче и попробовать решить заново(вполне вероятно, что не получится и это тоже нормально, просто повторяете все шаги заново, у меня бывали случаи, когда я одну и ту же задачу решал и по 10 раз, пока точно не буду уверен, что точно понял).</li><li>Четвертый совет – пройдитесь <a href="https://hackernoon.com/14-patterns-to-ace-any-coding-interview-question-c5bb3357f6ed">по этим 14 шаблонам</a>, особенно уделите внимание two pointers, sliding window и fast &amp; slow pointers, т.к. они чаще всего встречаются. Берете шаблон, находите задачи под этот шаблон(на странице с leetcode проблемами есть фильтр по тегам, нужно выбрать нужный тег, к примеру “Two pointers” или “Sliding window” и т.д.) и решаете столько задача, сколько нужно, чтоб закрепить эту тему.</li><li>Пятый и самый важный совет – практика, практика и еще раз практика, в начале мне хотелось каждый раз плакать от своей тупости, потому что не мог решать даже простые задачи и это не преувеличение, фраза – “какой же я тупой” не уходила из головы первые несколько месяцев и даже после решения 600 задач все еще бывают моменты, когда самооценка падает, если не получилось решить какую-то задачу, особенно если оказалось, что решается очень легко, но что важно – с каждой решенной задачей вы будете становиться лучше относительно себя.</li></ol><p>Минус литкода <a href="https://firecode.io/">решили на этой платформе</a>, где задачи даются один за другим, начиная с легких и повторяя уже решенные задачи, чтоб закрепить. Есть объяснение разных тем, после решения задачи можно посмотреть как другие решили, что очень полезно, т.к. ты видишь разные подходы решения одной и той же задачи.</p><h2>FAQ</h2><ol><li>Что делать, если не получается решить задачу?Если после 30-40 минут у вас не получилось решить задачу, то посмотрите решение, попробуйте найти видео решение этой задачи, как только посмотрели и разобрали, попробуйте решить заново, если не получилось, еще раз посмотрите и так по кругу. Время от времени возвращайтесь к старым задачам и решайте их заново, особенно если решение какой-то задачи далось вам с трудом.Я порой одну и ту же задачу решал по 10-15 раз, а то и больше</li><li>Сколько задач нужно решить, чтобы начать откликаться на вакансии?Тут все индивидуально, я полгода каждый день решал(сам или с помощью видео) несколько задач, решил где-то 300 задач и только в этот момент почувствовал почву под ногами, а уверенность почувствовал только после решение где-то 400-500 задач. Некоторым достаточно и 100-200 задач, к сожалению я не из их числа.</li><li>Какой язык программирования выбрать для решения задач?Если коротко – Python.Я начинал решать на php, потом перешел на go, после начал решать на java и наконец <a href="https://www.youtube.com/watch?v=0K_eZGS5NsU">после просмотра видео</a> решил попробовать python и с тех пор решаю на этом ЯП. Java – тратишь время на большие конструкции, к примеру – List&lt;Integer&gt; items = new ArrayList&lt;&gt;();<br />PHP – путался в аргументах функций, неудобно было в целом писать, хотя практически все время пишу на этом языкеGo – мало встроенных функций, даже min/max, теперь уже есть, но тогда не было, также нужно конвертировать int в float и обратно, тратишь лишнее время, хотя код и предсказуемыйPython – лаконичный код, много встроенных функций, которые помогают решать задачи (Counter, defaultdict, divmod, lambda и т.д.), время тратишь именно на решение задачи, а не на печатания и прочее, скорость на собеседовании очень важна.</li><li>Как найти время на задачи?<br />В моем случае я старался решать по 2 задачи в день, одну задачу до начала работы и вторую задачу после работы. На выходных уделял больше времени, смотрел видео, читал статьи, старался решать больше задач, также старался повторно решать старые задачи, чтобы закрепить тему и задачу.</li><li>Нужно ли покупать leetcode premium?<br />Самое полезное у premium – вы можете посмотреть в каких компаниях давали ту или иную задачу, если вы готовитесь к конкретной компании, то рекомендую, иначе достаточно бесплатной версии, т.к. видео объяснение задачи можно найти на канале Neetcode(ссылка ниже) и т.д.</li><li>Стоит ли покупать доступ к educative.io?<br />Очень много видел рекомендаций курса Grokking Coding Interview Patterns от educative, но не нашел этот курс очень полезным, единственное понравилось визуальное объяснение, но на мой взгляд лучше посмотреть видео на ютуб</li><li>Стоит ли покупать доступ к algoexpert.io?<br />На мой взгляд очень полезный ресурс, для каждой задачи есть подробное объяснение, чуть ли не каждое видео по 30-50 минут. На сайте постоянно проходят разные акции и можно ухватить все курсы на год за 99$, адекватная цена, приятный сайт, много тест кейсов для задач и сам редактор приятный и удобный</li></ol><figure><img src="https://media.tproger.ru/user-uploads/96915/2024-01-23/2b2f3e16-2951-4eec-a8ea-0962078e83fe.jpg" alt="" /></figure><h2>Результат</h2><ol><li>Достиг свою изначальную цель, ради которой и начинал решать алгоритмы – прохождение кодинг интервью, один из этапов, которые обязательны в FAANG компаниях, уже прошел в нескольких компаниях и что самое главное – теперь нет страха перед этим этапом.</li><li>Более глубоко начал понимать структуры данных, раньше понятия не имел, что такое heap, а сейчас имею полное представление об этой структуре, а также о других структурах.</li><li>В процессе работы начал чуть иначе смотреть на код, где-то видишь, что можешь использовать больше памяти и сократить time complexity, а где-то наоборот.</li><li>Последнее, но не по важности – фитнес для мозга, перешел из уровня – “не хочу – не буду”, до уровня – “хочу решать задачи каждый день”</li></ol><p>Читайте также на Tproger: <a href="https://tproger.ru/articles/kak-podgotovitsya-k-sobesedovaniyu-v-it-kompaniyu">как подготовиться к техническому интервью в ИТ-компанию</a> и <a href="https://tproger.ru/articles/algoritmy-i-struktury-dannyh-dlya-nachinajushhih">алгоритмы и структуры данных для начинающих</a>.</p><h2>Полезные ссылки</h2><ol><li>Пожалуй <a href="https://www.youtube.com/@NeetCode">самый полезный канал</a>, где человек в доступной форме объясняет задачу и решение.</li><li>Тоже <a href="https://www.youtube.com/@WilliamFiset-videos">очень много полезных видео</a> с объяснениями разных структур данных.</li><li><a href="https://www.youtube.com/c/BackToBackSWE">Объясняет на доске структуры данных, задачи</a>.</li><li><a href="https://www.youtube.com/@insidecode">insidecode</a></li><li><a href="https://www.youtube.com/@geekific/videos">geekific</a></li><li><a href="https://www.youtube.com/@MichaelMuinos/videos">MichaelMuinos</a></li><li><a href="https://www.youtube.com/c/NickWhite/videos">NickWhite</a></li><li><a href="https://www.youtube.com/channel/UCMrgnopgrjjIJn-xyYhZ7nA">Cracking FAANG</a></li></ol>]]></content:encoded>
    </item>
    <item>
      <title>IT-задачи о кофе, switch и шумах</title>
      <link>https://tproger.ru/articles/it-zadachi-o-kofe-switch-i-wumah</link>
      <comments>https://tproger.ru/articles/it-zadachi-o-kofe-switch-i-wumah?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Татьяна Бобкова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/it-zadachi-o-kofe-switch-i-wumah</guid>
      <description><![CDATA[<p>Собрали самые каверзные задачи на тему программирования по Go, C# и QA, которые удивили инженеров Ozon Tech, и делимся решениями.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/it-zadachi-o-kofe-switch-i-wumah">IT-задачи о кофе, switch и шумах</a>»</p>]]></description>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[C#]]></category>
      <category><![CDATA[Golang]]></category>
      <category><![CDATA[QA]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 12 Dec 2023 08:51:26 GMT</pubDate>
      <content:encoded><![CDATA[<p>В ноябре Ozon Tech и Tproger провели<a href="https://ozontechchallenge.tproger.ru/"> конкурс</a>, в котором участникам не нужно было ничего решать, а наоборот, прислать свои задачи команде инженеров.</p><p>Разобрали решения четырёх лучших задач и предлагаем вам тоже подумать над вариантами.</p><h2>1. Go: нужно ли использовать внешний пул?</h2><p>Дано:</p><ul><li>Master-slave postgres стенд (репликация асинхронная посредством patroni);</li><li>Внешний пул коннекшенов (pgpool/pgbouncer), приконекченный к мастеру.</li><li>Одно/несколько приложений с внутренним реализованным пулером, работающие с внешним пулом из предыдущего пункта.</li></ul><p>Вопросы:</p><ul><li>Не добавляет ли точек отказа наличие внешнего пулера, ведь он не реплицирован как postgres, и в случае его неработоспособности упадёт всё? Как и где архитектурно предусмотреть fallback-механизм для такого?</li><li>Есть ли вообще смысл использовать внешний пул? Если да, то какой, при условии что количество коннекшенов с реплик сервисов (даже с учётом разумной работы автоскейлера, если он есть) разумно и не превосходит значение в конфигурации postgres?</li><li>Предположим, что мы решили отказаться от внешнего пула. На кластере postgres произошёл failover (мастер переключился на реплику). Как быстро приложения переподключатся к новому мастеру? Возможна ли ситуация, что в используемых вами C# и Go пулерах не произойдёт инвалидация коннекшена?</li></ul><p>Автор задачи: Иосиф Петрович</p><p>Если вы хотите сначала решить задачу самостоятельно, то не открывайте решение инженеров сразу.</p><h2>2. C#: сколько кофе пьют коллеги?</h2><p>Разработайте систему для учёта потребления кофе в офисе и автоматического пополнения запаса кофейных зёрен. Система должна учитывать изменение потребительской активности, включая возрастающее потребление при завершении спринтов и снижающееся потребление во время праздничных дней.</p><p>Автор задачи: Александр Катков</p><h2>3. Go: когда лучше использовать оператор switch, а когда if / else?</h2><p>Абстрактный алгоритм в Go можно реализовать оператором switch на четыре варианта событий или четырьмя последовательными if-else. Когда целесообразно сделать через switch и чем тут Go отличается от остальных — С, Java, Kotlin и т. д.?</p><p>Автор задачи: Денис Пащенко</p><p>По его статистике только 10% кандидатов отвечают на вопрос правильно.</p><h2>4. QA: откуда шумы в ШУМе?</h2><p>Когда-то я работал в около-космической сфере. Мы разрабатывали ШУМ — широкополосный усилитель мощности СВЧ. Прибор состоит из трёх модулей:</p><ul><li>алюминиевый корпус, покрытый никелем с впаянными в него разъёмами;</li><li>СВЧ-часть на микрополосках с мощным усилительным транзистором;</li><li>умная система питания с прошивками ПО.</li></ul><p>Я проверял прибор в сборке. Прибор включали на половину мощности, нагревали до +90, охлаждали до -70, трясли сутками, делали вакуум, давление в 10 атмосфер, проверяли на влагостойкость и т. д.</p><p>По итогам проверки приборы показали себя отлично. Пришло время контрольной проверки на максимальную мощность, и тут в сигнале появился шум (паразитный сигнал). Непонятно, откуда он возникал, но этим была поражена вся партия приборов последней сборки.</p><p>Вопрос: как и откуда возникал этот сигнал, и какие действия мы предприняли, чтобы его найти?</p><p>Для меня эта задача оказалась очень сложной, так как пришлось применить все свои знания в материаловедении, микроэлектронике и СВЧ.</p><p>Автор задачи: Илья Баранов</p><p>На время конкурса участники попали в зазеркалье королевства Nozo, где всё происходит наоборот: код пишется слева направо, а тестирование начинается до разработки. Чтобы выбраться из зазеркалья, участники бросили вызов инженерам Ozon Tech и устроили им своё техсобеседование.</p><p>На конкурс прислали больше 90 задач по Go, C# и QA. Мы поделились четырьмя самыми каверзными. Если вы хотите решить задачи остальных участников, переходите <a href="https://ozontechchallenge.tproger.ru/">на сайт конкурса.</a></p><p>Хотя все задачи финалистов были увлекательными, победить и действительно выпить кофе с лидом команды инженеров удалось автору задачи по QA про шумы. Остальные финалисты получили мерч от Ozon Tech. А сколько задач решили вы?</p>]]></content:encoded>
    </item>
    <item>
      <title>Как я пытался писать красивый код</title>
      <link>https://tproger.ru/articles/kak-ya-pytalsya-pisat-krasivyj-kod</link>
      <comments>https://tproger.ru/articles/kak-ya-pytalsya-pisat-krasivyj-kod?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Intergalactic]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-ya-pytalsya-pisat-krasivyj-kod</guid>
      <description><![CDATA[<p>Недавно прошёл конкурс красоты кода. Участие по направлению Android в этом конкурсе было интересным опытом, которым я поделюсь в статье.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-ya-pytalsya-pisat-krasivyj-kod">Как я пытался писать красивый код</a>»</p>]]></description>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[Мобильная разработка]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 05 Oct 2023 10:08:06 GMT</pubDate>
      <content:encoded><![CDATA[<p>Недавно прошёл конкурс красоты кода. Участие по направлению Android в этом конкурсе было интересным опытом, которым я поделюсь в статье.</p><p>Содержание:</p><ul><li><a href="https://tproger.ru/#one">О конкурсе</a></li><li><a href="https://tproger.ru/#two">Задание по направлению Android</a></li><li><a href="https://tproger.ru/#three">Моё решение</a></li><li><a href="https://tproger.ru/#four">Решение ChatGPT</a></li><li><a href="https://tproger.ru/#five">Звонок другу</a></li><li><a href="https://tproger.ru/#six">Комментарий победителя в номинации «Изящный код» и его решение</a></li></ul><h2>О конкурсе</h2><blockquote>Компьютерный код может написать любой разработчик. Красивый код пишут лишь единицы. Чистый, изящный, лаконичный, читаемый и понятный код, который работает без багов — это настоящее произведение искусства в сфере разработки.</blockquote><p>Для участников стояла задача написать красивый код по одному из пяти направлений (Python, Java, Data Science, Front-end, Android).</p><p>Каждое направление предусматривало 3 номинации:</p><ul><li>Краса кода — решение, признанное максимально эффективным по мнению жюри;</li><li>Изящный код — самое лаконичное решение, соответствующее поставленной задаче;</li><li>Звезда кода — самое неординарное решение по общей оценке жюри.</li></ul><p>Призы конкурса: iPhone 14, умная колонка и приглашение на вечеринку в честь Дня программиста.</p><h2>Задание по направлению Android</h2><p>Вводные данные:</p><h2>Моё решение</h2><p>Итак, нам нужно вывести список категорий и характеристик. При этом элементы в списке должны находиться разные типы элементов: категория, характеристика, концевик категории (её ID).</p><p>Первое, что пришло на ум — List. Это плохое решение, ведь так в этот список можно положить вообще всё, что угодно.</p><p>Я посмотрел, что объединяет входные дата-классы. Воспользовавшись nullable-свойствами, я создал общий дата-класс. В названии его я буквально написал, что он содержит.</p><p>Объекты этого класса будут наполнять результирующий список.</p><p>Дальше ничего не интересного: я просто воспользовался вложенными циклами.</p><p>С помощью именованных аргументов конструктора класса, в список сначала добавляется категория, потом все соответствующие характеристики, затем ID категории. Такое довольно простое решение.</p><p>Небольшая оптимизация:</p><p>В данном случае после добавления характеристики (feature) в итоговый список (categoriesWithFeatures), она удаляется из списка характеристик (mutableFeatures), поэтому следующая итерация цикла пройдёт быстрее, так как в списке будет меньше элементов.</p><p>Однако в данном случае необходимо создавать mutableFeatures (изменяемый дупликат списка features), что может быть неэффективно по памяти, если начальный список достаточно большой.</p><p>Эта оптимизация подходила бы, если входная функция возвращала изменяемый список:</p><p>После участия в конкурсе я нашёл конструкции языка и методы, которые позволяют улучшить код. Например, вместо моего дата-класса больше подошёл бы Sealed Class с тремя потомками: Категорией, Характеристикой и ID категории.</p><h2>Решение ChatGPT</h2><p>Я попросил ChatGPT решить поставленную задачу, и вот что он написал:</p><p>Моё решение лучше этого, потому что оно, как минимум, работает. Ура, моё решение лучше решения ChatGPT, плюс самооценка!</p><p>Что же делает наш умный товарищ:</p><ul><li>Пытается добавить элемент к неизменяемому списку (currentCategory?.features?.add(feature));</li><li>Пишет комментарии в решении, которое должно читаться без комментариев.</li></ul><p>Хорошо, давайте закроем на это глаза. Закрыли, но решение всё ещё плохое: оно не соответствует поставленной задаче:</p><ul><li>Основная функция в итоге возвращает список объектов CategoryWithFeatures. Этот класс содержит данные категории и список характеристик. Всё это он запихал в один класс. Теперь нет отдельных элементов категории, характеристики и ID категории, которые должны быть в результирующем списке по условию задачи.</li><li>Его цикл работает только, если во входных данных характеристики идут строго по порядку: сначала характеристики одной категории, потом другой. В противном случае в цикле создаются дубликаты категорий.</li></ul><p>Вот, что мы в итоге получаем:</p><figure><img src="https://media.tproger.ru/user-uploads/73470/2023-10-04/5e041999-6656-43ee-990c-fd8869c18180.jpeg" alt="" /><figcaption>Входные и выходные данные, дублирование категорий</figcaption></figure><p>Я также показал своё решение chatGPT и попросил его улучшить. Вот его версия моего решения:</p><p>Мой дата-класс он оставил без изменений и поменял саму функцию. Теперь сначала с помощью функции groupBy создаётся Map&gt;, где ключи — ID категории, значения — списки характеристик. Потом всё те же вложенные циклы, только теперь нужные характеристики не нужно искать, а просто брать из созданного Map.</p><p>В итоге:</p><ul><li>Результат работы такой же;</li><li>Вложенные циклы остались;</li><li>Перед вложенными циклами появились: ещё один цикл от функции groupBy и дополнительная переменная;</li><li>Код стал короче, но, как по мне, его читаемость не изменилась.</li></ul><h2>Звонок другу</h2><p>Не получив фидбека от организаторов конкурса, я попросил его у друга. Вместе с фидбеком я получил ещё один вариант решения:</p><blockquote>Я попытался переписать код, но в итоге сложность по времени получилась такая же. Пока что не придумал другого варианта.</blockquote><p>Действительно, во втором цикле из-за функции addAll (которая циклически добавляет все элементы списка featuresFromMap) у нас снова получаются вложенные циклы. При этом читаемость кода снизилась.</p><p>К слову, весь первый цикл делает почти то же самое, что и функция groupBy. Разница в том, что groupBy вернёт Map&gt;, а цикл — MutableMap&gt;.</p><blockquote>Мне не нравится моя мапа на самом деле. Я добавил список не фичей, а этого класса только из-за того, что не хотел дополнительно забивать память потом. Хотя мб я, кстати, неправильно посчитал, и такой вариант ничем не отличается. Короче, в промышленном коде так делать не стоит.</blockquote><h2>Комментарий победителя конкурса и его решение</h2><p>Давид Жубрёв, победитель в номинации «Изящный код», разрешил опубликовать его решение:</p><p>Рассмотрим, что здесь происходит. Метод flatMap в соответствии с лямбда-функцией преобразует каждый элемент списка категорий в List, где первый элемент — объект категории. Список характеристик фильтруется по ID категории и преобразовывается в массив. С помощью оператора * каждый элемент массива вкладывается в упомянутый List. Последний элемент List — ID категории.<br />После этого flatMap избавляется от вложенных списков и возвращает одномерный список всех элементов.</p><p>Хоть в результате и получается List, решение очень лаконичное и понятное, что идеально соответствует номинации. По временной сложности всё остаётся так же, но выглядит лучше. Если добавить сюда другую структуру данных, например, тот же Sealed Class, то будет, возможно, лучшее решение поставленной задачи.</p><p>Победитель прокомментировал конкурс и своё участие в нём:</p><blockquote>Я не возлагал больших надежд на победу, для меня это был, скорее, небольшой фан. Я был очень удивлен, когда мне написали о победе, но было крайне приятно)</blockquote><p>Спасибо за прочтение данной статьи! Буду рад узнать ваше мнение о конкурсе и представленных решениях ?</p>]]></content:encoded>
    </item>
    <item>
      <title>Метаэвристические решения Задачи Коммивояжёра</title>
      <link>https://tproger.ru/articles/metaevristicheskie-podhody-k-reweniyu-zadachi-kommivoyazhyora</link>
      <comments>https://tproger.ru/articles/metaevristicheskie-podhody-k-reweniyu-zadachi-kommivoyazhyora?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Randolph Carter]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/metaevristicheskie-podhody-k-reweniyu-zadachi-kommivoyazhyora</guid>
      <description><![CDATA[<p>В данной статье рассматриваем и реализуем на Python различные подходы (GA, ACO, SA) к решению задачи коммивояжёра.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/metaevristicheskie-podhody-k-reweniyu-zadachi-kommivoyazhyora">Метаэвристические решения Задачи Коммивояжёра</a>»</p>]]></description>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 28 Sep 2023 08:40:50 GMT</pubDate>
      <content:encoded><![CDATA[<p>В данной статье рассматриваем и реализуем на Python различные подходы (GA, ACO, SA) к решению задачи коммивояжёра.</p><h2>О задаче</h2><p>Задача коммивояжёра (Travelling Salesman Problem, TSP) — задача комбинаторной оптимизации. Как правило, её суть сводится к поиску оптимального пути, проходящего через все промежуточные пункты по одному разу и возвращающегося в исходную точку.</p><p>Для возможности применения математического аппарата к решению задачи мы представим её в виде симметричного графа. Вершины графа соответствуют условным городам, а рёбра — путям сообщения между этими городами. Каждому ребру сопоставим критерий выгодности маршрута — расстояние между городами. В целях упрощения задачи будем считать, что граф является полностью связным.</p><p>Для визуализации задачи будем использовать класс TSP (программный код представлен ниже). Этот класс включает в себя функции, необходимые для отрисовки точек, маршрутов, а также интерактивной легенды, на элементы которой можно нажимать для того, чтобы скрыть / отобразить выбранные пути. Сгенерируем набор точек, воспользовавшись функцией points = generate_problem(20), и выведем его на экран с помощью TSP(points=points, paths=None).</p><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-20/39d6c77a-41d7-4105-8a48-66881dbfae01.png" alt="" /></figure><p>Стоит отметить, что в программной реализации решениями является список объектов класса Path, которые содержат в себе информацию о последовательности точек маршрута, о его длине и названии (используются для легенды на графике).</p><p>Но откуда берутся эти решения?</p><p>Поскольку коммивояжёр в каждом из условных городов встаёт перед выбором следующего города из тех, что он ещё не посетил, существует (n-1)! / 2 маршрутов для симметричной задачи. Если городов, например, 20, то возможных маршрутов будет 60 822 550 204 416 000. Для того, чтобы перебрать такое количество вариантов и найти оптимальный путь, понадобятся огромные вычислительные мощности и куча времени.</p><p>К счастью, на практике зачастую не требуется находить именно точное решение. Достаточно и субоптимального, которое будет близко к оптимальному пути.</p><p>При такой постановке задачи для её решения можно воспользоваться метаэвристическими алгоритмами, которые значительно ускорят процесс нахождения решения.</p><h2>Метаэвристические алгоритмы</h2><p>Метаэвриистика — метод оптимизации, многократно использующий простые правила для достижения субоптимального решения.</p><p>В данной статье мы рассмотрим следующие алгоритмы решения задачи:</p><ol><li><b>Генетический алгоритм</b> (Genetic Algorithm, GA), относящийся к классу эволюционных методов;</li><li><b>Муравьиный алгоритм</b> (Ant Colony Optimization, ACO), относящийся к классу методов “роевого” интеллекта;</li><li><b>Алгоритм имитации отжига</b> (Simulated annealing, SA), относящийся к классу методов, имитирующих физические процессы.</li></ol><p>Каждый из вышеописанных алгоритмов будет использовать методы для вычислений расстояний между точками. Объединим данный функционал в класс Base, от которого в дальнейшем будем наследовать общие методы.</p><p>Здесь:</p><ul><li>euclidean_dist() используется для нахождения Евклидова расстояния между двумя 2D точками;</li><li>calculate_dist() рассчитывает длину указанного пути на основе матрицы расстояний;</li><li>distance_matrix(), собственно, эту матрицу вычисляет.</li></ul><h3>Генетический алгоритм</h3><p>Генетический алгоритм — алгоритм поиска, используемый для решения задач оптимизации и моделирования путём случайного подбора, комбинирования и вариации искомых параметров с использованием механизмов, аналогичных естественному отбору в природе.</p><p>Данные механизмы применяются к особям, каждая из которых в программной реализации представляет из себя список индексов 2D точек — последовательность, в которой эти точки следует обойти для достижения кратчайшего пути. Начальная популяция состоит из особей, случайно сгенерированных функцией initialization().</p><p>После создания начальной популяции запускается цикл операций, направленных на постепенную эволюцию особей:</p><ul><li>fitness_sort() ранжирует особи в текущей популяции с помощью функции приспособления (чем короче маршрут, содержащийся в геноме особи, тем лучше);</li><li>selection() отбирает часть наиболее приспособленных особей из текущей популяции;</li><li>crossover() скрещивает особей текущей популяции, соединяя части генома от двух случайно выбранных родителей (панмиксия);</li><li>mutation() случайным образом делает перестановки в геноме некоторых особей текущей популяции.</li></ul><p>Когда цикл завершит свою работу, мы используем лучшую особь (маршрут) из последней популяции в качестве решения задачи.</p><p>Отметим, что результаты работы алгоритма во многом зависят от заданных гиперпараметров:</p><ul><li>population — общее число особей, участвующих в одной итерации;</li><li>iter — максимальное количество итераций алгоритма;</li><li>s — определяет, сколько лучших особей попадет в следующую популяцию (в процентном соотношении);</li><li>m — определяет, как часто особи в популяции мутируют (в процентном соотношении).</li></ul><p>Ниже приводится программная реализация данного алгоритма.</p><p>Такой результат получается при запуске алгоритма с набором гиперпараметров GA(population=1500, iter=40, s=0.2, m=0.5):</p><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-21/790413ff-9a87-48e4-aef0-c115af615382.png" alt="" /></figure><h3>Муравьиный алгоритм</h3><p>Муравьиный алгоритм — один из эффективных алгоритмов для нахождения приближённых решений задачи коммивояжёра, а также решения аналогичных задач поиска маршрутов на графах. Суть подхода заключается в анализе и использовании модели поведения муравьёв, ищущих пути от колонии к источнику питания.</p><p>Изначально условные муравьи передвигаются случайным образом, охватывая различные маршруты. Во время передвижения муравьи оставляют след из феромона, обозначая эти самые маршруты. Соответственно, чем короче получился путь, тем большее количество феромона за одинаковое количество времени муравьи на нём оставят. Феромон с течением времени испаряется. Из-за этого на длинных маршрутах остаётся меньше феромона, чем на коротких, даже если по ним передвигалось одинаковое количество муравьёв. Муравьи будут чаще выбирать самую “пахучую тропинку” и забывать пути с меньшим количеством феромона.</p><p>В программной реализации мы на каждой итерации цикла имитируем поведение каждого муравья из колонии:</p><ul><li>create_indx() формирует маршрут муравья (список индексов точек) и подсчитывает длину;</li><li>select_i() отвечает за выбор муравьём каждой последующей точки маршрута внутри функции create_indx();</li><li>update_pm() обновляет матрицу феромона.</li></ul><p>Формулой ниже описывается вероятность, с которой муравей перейдёт из точки i в точку j (используется в функции create_indx()):</p><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-22/567e4e29-c35b-4adc-8e38-5ec89563dec3.png" alt="" /></figure><p>Здесь:</p><ul><li>τ(i,j) — количество феромона на ребре i, j (значение из матрицы феромона);</li><li>α — гиперпараметр, контролирующий влияние τ(i,j) (задаётся пользователем);</li><li>η(i,j) — привлекательность ребра i, j, равняется 1 / d(i,j) (обратному значению из матрицы расстояний);</li><li>β — гиперпараметр, контролирующий влияние η(i,j) (задаётся пользователем).</li></ul><p>После формирования маршрутов необходимо обновить матрицу феромона (за это отвечает функция update_pm()). Обновление происходит по следующему правилу:</p><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-22/701c4f2f-1114-4cf0-9a39-85c93291dcc6.png" alt="" /></figure><p>Здесь:</p><ul><li>τ(i,j) — количество феромона на ребре i, j (значение из матрицы феромона);</li><li>ρ — скорость испарения феромона (задаётся пользователем);</li><li>Δτ(i,j) — количество отложенного феромона, равняется q / d(i,j) (интенсивность феромона, делённая на длину маршрута из точки i в точку j).</li></ul><p>В конце каждой итерации находим лучший маршрут из маршрутов, пройденных на текущей итерации, и сравниваем его с абсолютно лучшим найденным маршрутом. Если новое решение оказалось лучше, то записываем его в отдельную переменную. Последний записанный маршрут и будет являться решением задачи.</p><p>Так же, как и генетический алгоритм, данный алгоритм зависим от гиперпараметров:</p><ul><li>ants — общее количество агентов (муравьев), задействованных в одной итерации;</li><li>iter — максимальное количество итераций алгоритма;</li><li>α — коэффициент, контролирующий влияние феромона на ребре;</li><li>β —коэффициент, контролирующий влияние привлекательности маршрута (величина, обратно пропорциональная длине маршрута);</li><li>ρ — коэффициент испарения феромона, который отражает степень взаимного влияния между муравьями, как правило, значение равно [0, 1], что предотвращает бесконечное накопление феромона;</li><li>q — интенсивность феромона, которая представляет собой общее количество феромонов, в определённой степени влияет на скорость сходимости алгоритма.</li></ul><p>Ниже приводится программная реализация данного алгоритма.</p><p>Такой результат получается при запуске алгоритма с набором гиперпараметров ACO(ants=100, iter=20, a=1.5, b=1.2, p=0.6, q=10):</p><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-21/8a9b40ac-531e-43ec-a69d-28c98ec783fa.png" alt="" /></figure><h3>Алгоритм имитации отжига</h3><p>Алгоритм имитации отжига — метод решения задачи глобальной оптимизации. Он основывается на имитации физического процесса, который происходит при кристаллизации вещества, в том числе при отжиге металлов. Предполагается, что в определённый момент атомы вещества практически выстроены в кристаллическую решётку, но ещё допустимы переходы отдельных атомов из одной ячейки в другую. Активность атомов тем больше, чем выше температура, которую постепенно понижают, что приводит к тому, что вероятность переходов в состояния с большей энергией уменьшается. Устойчивая кристаллическая решётка соответствует минимуму энергии атомов, поэтому атом либо переходит в состояние с меньшим уровнем энергии, либо остаётся на месте.</p><p>В программной реализации под энергией понимается длина получившегося маршрута. Изначально маршрут задаётся случайно. На каждой итерации с помощью перестановки пары индексов мы генерируем новый маршрут. На основе его длины, длины предыдущего маршрута и текущего значения температуры функция is_acceptable() определяет, совершать ли переход в новое состояние или нет. Вероятность перехода рассчитывается по формуле:</p><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-22/4db68431-4fd9-44fc-aef3-bb3a03a1abda.png" alt="" /></figure><p>Здесь:</p><ul><li>ΔF(i) — изменение “энергии” (разность между длинами вероятного и текущего маршрута);</li><li>T(i) — значение температуры на i-ой итерации алгоритма.</li></ul><p>В конце каждой итерации система “остывает”: параметр, отвечающий за температуру, уменьшается. Когда алгоритм отработает отведённое количество итераций, он вернёт минимальный найденный маршрут, являющийся решением задачи.</p><p>Гиперпараметры алгоритма:</p><ul><li>iter — максимальное количество итераций алгоритма;</li><li>t — начальная температура поиска, уменьшается по мере продвижения поиска;</li><li>g — коэффициент, влияющий на изменение температуры.</li></ul><p>Ниже приводится программная реализация данного алгоритма.</p><p>Такой результат получается при запуске алгоритма с набором гиперпараметров SA(iter=20000, t=100, g=0.6):</p><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-21/1d50171f-5faf-43bf-b8b6-23eb942c5aa6.png" alt="" /></figure><h2>Сравнение алгоритмов</h2><p>Сравнивать алгоритмы затруднительно, потому что — как упоминалось выше — результаты во многом зависят от подобранных гиперпараметров. Так же нужно учитывать, что существует довольно много различных вариаций реализации алгоритмов, в зависимости от которых результаты тоже будут отличаться.</p><p>Если же выбирать лучшую реализацию из тех трёх, что были описаны в данной статье, то я бы отдал предпочтение муравьиному алгоритму. Он довольно быстр и, что наиболее важно, показывает хорошие результаты даже при большом количестве исходных данных. Ниже приводятся примеры решения задачи на 100 и 200 точек.</p><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-21/f79d6484-9458-459b-a567-d5fd68d1d3b3.png" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/90129/2023-09-21/f5114ebc-4ee9-4cdf-b41c-141dec48301a.png" alt="" /></figure><h2>Заключение</h2><p>Таким образом, мы разобрали одни из самых популярных метаэвристических подходов к решению задачи коммивояжёра: генетический алгоритм, муравьиный алгоритм и алгоритм иммитации отжига.</p><p>Подробнее ознакомиться с кодом данных алгоритмов и поэкспериментировать с подбором гиперпараметров можно на GitHub’е по данной <a href="https://github.com/r4nd0lph-c/travelling_salesman_problem">ссылке</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Задачи с собеседований для разработчиков в IBM, Amazon и Microsoft</title>
      <link>https://tproger.ru/articles/intervyu-dlya-razrabotchikov-v-ibm-amazon-i-microsoft-raundy-i-zadachi</link>
      <comments>https://tproger.ru/articles/intervyu-dlya-razrabotchikov-v-ibm-amazon-i-microsoft-raundy-i-zadachi?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Рафаил Агазода]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/intervyu-dlya-razrabotchikov-v-ibm-amazon-i-microsoft-raundy-i-zadachi</guid>
      <description><![CDATA[<p>Собрали отзывы о собеседованиях на должности разработчиков ПО в IBM, Amazon и Microsoft. Составили подборку задач и вопросов от HR.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/intervyu-dlya-razrabotchikov-v-ibm-amazon-i-microsoft-raundy-i-zadachi">Задачи с собеседований для разработчиков в IBM, Amazon и Microsoft</a>»</p>]]></description>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Microsoft]]></category>
      <category><![CDATA[Карьера]]></category>
      <category><![CDATA[Собеседование]]></category>
      <category><![CDATA[Amazon]]></category>
      <category><![CDATA[IBM]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 22 Sep 2023 13:26:53 GMT</pubDate>
      <content:encoded><![CDATA[<p>Собрали отзывы о собеседованиях на должности разработчиков ПО в IBM, Amazon и Microsoft с сайта <a href="https://www.codingninjas.com/">Coding Ninjas</a>.</p><p>Соискатели рассказали, как готовились к интервью, какие задачи решали на первых раундах и на какие вопросы отвечали перед HR.</p><h2>Собеседование в Amazon</h2><p>Автор этого отчета последовательно готовился к собеседованию в “большую пятерку” FAANG еще с обучения в бакалавриате. Также он писал свой диплом так, чтобы он казался более значимым в глазах собеседующих. На подготовку к собеседованиям у автора ушло 3 года, и его взяли на работу.</p><h3>Советы</h3><ol><li>Решайте все задачи по теме “Конкурентное программирование”. Также стоит регулярно решать задачки с сайтов как Leetcode, Interviewbit и Codeforces.</li><li>Регулярно занимайтесь конкурсным программированием.</li><li>Постоянно обновляйте свое резюме. В нем должны быть хотя бы 2-3 проекта хорошего уровня, чтобы впечатлить интервьюера.</li><li>Не врите в резюме.</li></ol><h3>Раунд 1</h3><h3>1. Рассчитать объем воды</h3><p>Дан массив ‘arr’ типа long размера ‘n’. При этом ‘arr[i]’ обозначает высоту столбца ‘i’.</p><p>Рассчитайте объем воды, который можно было бы собрать, если бы из столбцов массива можно было собрать фигуру. Ширина каждого столбца одинакова и равна 1.</p><p>Например, ‘n’ = 6, ‘arr’ = [3, 0, 0, 2, 0, 4]. Тогда ответом будет 10.</p><figure><img src="https://media.tproger.ru/user-uploads/48741/2023-09-22/a2fabd7a-ad52-47c5-bb30-bcf7252a9897.png" alt="" /></figure><p>Нам нужно реализовать функцию, которая высчитывала бы:</p><ol><li>В первой строке целое число ‘n’, обозначающее размер массива/списка.</li><li>Во второй строке ‘n’ целых чисел, разделенных пробелами, представляющих высоту столбиков.</li></ol><p>Вывод должен содержать целое число, обозначающее количество воды, которое может быть собрано.</p><h3>2. Реализация LRU-кеша</h3><p>Разработать и реализовать структуру данных для LRU-кеша для поддержки следующих операций:</p><ol><li>get(key) – Возвращает значение кэша, если он есть в памяти. В противном случае, функция должна вернуть -1.</li><li>put(key, value) – Вставить значение в кэш, если ключа еще не существует, или обновить значение ключа, если ключ уже существует. Перед обновлением элемента кэш должен удалить последнее использованное значение.</li></ol><p>При этом у кэша есть емкость, то есть максимальное количество ключей, которые могут храниться в памяти одновременно. Получение доступа к ключу должно определяться как операция put или get. Также последний использованный или обновленный ключ должен дольше всех храниться в памяти.</p><p>Первая строка ввода должна содержать два разделенных пробелом целых числа ‘C’ и ‘Q’, обозначающих емкость кэш-памяти и количество выполняемых операций соответственно.</p><p>Следующие ‘Q’ строк содержат операции, по одной на строку. Каждая операция начинается с целого числа, обозначающего тип операции.</p><p>Если число равно 0, то операция относится к первому типу, и за ней следует один целочисленный ключ.</p><p>Если число равно 1, то операция относится ко второму типу, и за ней следуют два целых числа key и value (в таком порядке), разделенные пробелами.</p><p>Для каждой операции типа 0 выведите целое число в одной строке, которое обозначало бы значение ключа, если ключ существует, или -1.</p><p>Значение Q не меньше 1 и не больше 10^4. Значение C не меньше 1 и не больше 10^5. В выводе не может быть значения меньше 1 и больше 10^9. Время выполнения операции не должно превышать секунды.</p><h3>Раунд 2</h3><p>На этом раунде присутствовал HR, разговор происходил наедине в Google Meet. Вопросы от HR:</p><ol><li>Кто является для вас примером для подражания?</li><li>Что вы ожидаете от этой работы?</li></ol><h2>Собеседование в IBM</h2><p>Автор этого отзыва готовился к интервью 4 месяца.</p><h3>Советы</h3><ol><li>Отработайте не менее 250 вопросов по программированию и разберитесь с концепциями ОС, сетей и баз данных.</li><li>В резюме должно быть не менее двух хороших проектов.</li><li>Изучите нюансы конкретной компании перед тем, как прийти на интервью.</li><li>Не врите в резюме.</li></ol><h3>Раунд 1</h3><h3>1. Сортировка массива</h3><p>Вам дан массив ‘arr’, состоящий из ‘n’ элементов. Каждый элемент массива равен 0, 1 или 2. Отсортируйте элементы массива в порядке возрастания. Не создавайте новый массив, просто внесите изменения в существующий.</p><p>Ввод должен содержать две строки, в которой первая содержит целое число, обозначающее количество элементов массива, а вторая содержит элементы массива.</p><p>Сперва автор использовал метод сортировки, но интервьюер попросил его не делать этого. Тогда автор просто написал функцию, которая запоминает количество 0, 1 и 2 в массиве.</p><h3>2. Задача об отрезании веревки</h3><p>Дана веревка длиной ‘N’ единиц. Она может быть разрезана на части различной длины, и каждый отрезок имеет свою стоимость. Определите максимальное количество вариантов, на которые можно разрезать веревку, вместе с ценами на каждый отрезок.</p><p>Размеры отрезков могут варьироваться от 1 до N. При этом сумма отрезков должна равняться N.</p><p>Первая строка ввода должна содержать целое число ‘N’, обозначающее длину веревки.</p><p>Вторая строка должна содержать вектор ‘A’ размера ‘N’, который показывает стоимость получившихся отрезков, где каждый индекс массива – это поддлина, а элемент с этим индексом – стоимость для этой поддлины.</p><p>Поскольку длина отрезка не может равняться 0, то нулевой индекс вектора будет представлять первую поддлину отрезка. Следовательно, индекс N-1 будет представлять стоимость для длины ‘N’.</p><h3>Раунд 2</h3><p>Интервьюер спрашивал о проектах, и автор рассказал о них. Затем интервьюер задал несколько вопросов по концепциям ОС.</p><p>Вопросы HR:</p><ol><li>Какие ваши сильные и слабые стороны?</li><li>Кем вы видите себя через 5 лет?</li></ol><h2>Собеседование в Microsoft</h2><p>Автор готовился к собеседованию в течение полугода. В частности, автор решил сделать упор на СУБД и объектно ориентированное программирование.</p><h3>Советы</h3><ol><li>Практикуйтесь в вопросах по структурам данных и алгоритмам. Можете тренироваться на InterviewBit и выполнять все задания по структурам данных и алгоритмам, которые задают на последних интервью.</li><li>Решайте задачи на Leetcode. Также стоит участвовать в еженедельных конкурсах, чтобы знать, какие ваши слабые места нужно улучшить.</li><li>Также стоит изучить основные понятия операционных систем и баз данных.</li><li>Проведите исследование целей компании и будьте готовы задать некоторые вопросы, связанные с компанией, которые покажут ваш интерес к компании.</li><li>Ваше резюме должно состоять в основном из навыков, проектов и достижений.</li><li>Никогда не лгите в своем резюме.</li></ol><h3>Раунд 1</h3><p>В этом раунде были даны три задачи по программированию, на решение которых отводилось чуть больше часа.</p><h4>1. Ближайшее число, кратное 10</h4><p>Вам дано целое число N. Найдите ближайшее к нему число, кратное 10. Если расстояние до чисел равное, выберите меньшее из них. К примеру, если дано число 3, то правильными ответами будут и 30, и 40. В этом случае стоит вывести 30.</p><h3>2. Вычислить день недели</h3><p>Напишите функцию, которая вычисляет день недели для любой даты в прошлом или будущем. К примеру, 28 августа 2020 года приходится на пятницу. Следовательно, ответ должен быть “Пятница”.</p><p>Ввод при этом должен содержать три целых числа, разделенных пробелами, которые обозначали бы день, месяц и год соответственно.</p><p>Вывод должен содержать значения из списка {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}.</p><p>Также есть ограничения по вводу: число дней не должно превышать 31, число месяцев не должно превышать 12, а год не должен превышать 2,000,000. Кроме того, все эти значения не могут быть меньше 1.</p><h4>3. Удалить N значений после M значений</h4><p>У вас есть список и два целых числа «N» и «M». Нужно удалить «N» узлов в списке после количества узлов «M». Иными словами, нужно отсчитать M узлов, после чего удалить N узлов, и так до конца списка.</p><p>Первая строка ввода должна содержать элементы односвязного списка, разделенные одним пробелом. Список должен завершаться -1. Следовательно, -1 никогда не будет элементом списка.</p><p>Вторая строка должна содержать два целых числа ‘N’ и ‘M’, разделенных одним пробелом.</p><p>Вывод должен содержать итоговый список.</p><h3>Раунд 2</h3><p>В этом раунде соискатели должны были написать код на бумаге. Он должен быть полностью рабочим. Можно использовать функции библиотек, но нужно объяснить, зачем они понадобились и как работают.</p><h4>1. Найти элемент последовательности</h4><p>Есть последовательность: 1, 11, 21, 1211, 111221, 312211, 13112221,...</p><p>Она строится так. Первое число читается как “один один”, точнее, как “one One”. Значит, и второе число будет “one one”, то есть 11. Число 11 читается как “two One”, то есть третье число будет равно 21. Число 21 читается как “one Two one One”, то есть четвертое число будет равно 1211. И так далее.</p><p>Нужно написать код, который позволял бы найти N элемент последовательности. При этом N должно быть не меньше 1 и не больше 40.</p><h4>2. Составить самое большое число из элементов массива</h4><p>Вам дан массив ‘ARR’ длины N, состоящий из неотрицательных целых чисел. Используя только эти заданные числа, переставьте их так, чтобы из них составлялось максимально возможное число.</p><p>К примеру, задан массив с элементами ’32’, ‘8’, ’29’. Вы должны расположить числа в порядке ‘8’, ’32’, ’29’. Тогда из них можно будет составить максимальное число 83229. Порядок цифр внутри элементов массива изменить нельзя.</p><h3>Раунд 3</h3><p>На этом этапе интервьюеры общались с каждым соискателем лично, лицом к лицу.</p><h4>1. Упростить путь к файлу</h4><p>Вам дан путь к файлу/каталогу в стиле Unix длиной N. В файловой системе в стиле Unix точка (.) относится к текущему каталогу. Двойная точка (..) относится к предыдущему каталогу относительно текущего каталога. Если между двумя каталогами имеется несколько косых черт, вы должны превратить их в одну косую черту.</p><p>От вас требуется упростить путь и задать конечный пункт в структуре каталогов.</p><p>Упрощенный путь всегда должен начинаться с косой черты (/), а между именами двух каталогов должна быть одна косая черта. На конце пути не должно быть косой черты.</p><p>Ввод должен содержать число Т, которое указывает, сколько каталогов на пути к файлу нужно отобразить. Кроме того, Т не может быть меньше 1 и больше 100.</p><h4>2. Упростить полином</h4><p>В странах бывшего СССР полином называют многочленом. Вам дается полином. К примеру, это будет 5x^3 + 2x^3 + 6x^4 + 2. Нужно упростить его.</p><p>Количество элементов полинома не должно быть равно нулю и превышать 10, а степени чисел и коэффициенты не должны превышать 10^5.</p><h3>Раунд 4</h3><p>На этом этапе интервьюер спрашивал соискателя о его проектах. Вопросы интервьюера:</p><ol><li>Расскажите обо всех своих проектах.</li><li>Какая структура у ваших проектов?</li><li>Как вы проходили летнюю стажировку?</li><li>Что такое линейная регрессия?</li></ol><h3>Раунд 5</h3><p>Этап собеседования с HR. Вопросы:</p><ol><li>Что такое СУБД?</li><li>Объясните ACID.</li><li>Объясните двухуровневую и трехуровневую архитектуру СУБД.</li><li>Что такое независимость от схемы в СУБД?</li></ol><h2>Заключение</h2><p>Надеемся, подборка оказалась полезной. Судя по всему, она предназначена для миддлов: соискатели указывали, что сложности задач была средней, но отнюдь не простой. А получилось ли у вас решить эти задачи?</p><p>Пишите в комментариях, стоит ли и дальше выкладывать подборки задач с интервью и, если стоит, для каких должностей.</p>]]></content:encoded>
    </item>
    <item>
      <title>Три задачи на знание Java от ChatGPT</title>
      <link>https://tproger.ru/problems/tri-zadachi-na-znanie-java-ot-chatgpt</link>
      <comments>https://tproger.ru/problems/tri-zadachi-na-znanie-java-ot-chatgpt?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Рафаил Агазода]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/tri-zadachi-na-znanie-java-ot-chatgpt</guid>
      <description><![CDATA[<p>Языковая модель ChatGPT составила простую, среднюю и сложную задачи по Java. Сможете ли вы решить все три задачи?</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/tri-zadachi-na-znanie-java-ot-chatgpt">Три задачи на знание Java от ChatGPT</a>»</p>]]></description>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Нейронные сети]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 23 Jan 2023 12:30:13 GMT</pubDate>
      <content:encoded><![CDATA[<p>Попросили языковую модель ChatGPT составить три задачи на знание Java: простую, среднюю и сложную.</p><p>К первым двум нейросеть прикрепила ответы, но третья задача осталась нерешённой. Сможете ли вы справиться с ней?</p><h2>Простая задача по Java</h2><p>Напишите программу на Java, которая будет считывать массив целых чисел и выводить на экран их сумму и среднее арифметическое.</p><p>Подсказки:</p><ul><li>Для считывания массива целых чисел используйте Scanner или BufferedReader.</li><li>Для вычисления суммы и среднего арифметического используйте цикл for.</li><li>Не забудьте проверить ввод на корректность (например, что введено число и не превышает максимально возможное значение для int).</li></ul><h2>Задача средней сложности по Java</h2><p>Напишите класс “Решето Эратосфена” для нахождения всех простых чисел в диапазоне от 2 до n. Класс должен иметь метод “просеивание” для построения решета и метод “вывод” для вывода всех найденных простых чисел.</p><h2>Сложная задача по Java</h2><p>Реализуйте класс “Матрица” с методами:</p><ol><li>Конструктор для создания матрицы размером nxm с нулевыми значениями.</li><li>Метод “setValueAt(int i, int j, int value)” для установки значения элемента в матрице по индексу i, j.</li><li>Метод “getValueAt(int i, int j)” для получения значения элемента в матрице по индексу i, j.</li><li>Метод “multiplyByScalar(int scalar)” для умножения каждого элемента матрицы на скаляр.</li><li>Метод “add(Matrix m)” для сложения двух матриц.</li><li>Метод “transpose()” для транспонирования матрицы.</li><li>Перегрузите оператор “+” для сложения двух матриц и оператор “*” для умножения матрицы на скаляр.</li><li>Реализуйте итератор для класса матрица, чтобы проитерироваться по всем элементам матрицы.</li></ol><p>Проверьте работу класса с помощью JUnit тестов.</p><p>Подсказки:</p><ol><li>Создайте класс “Matrix” с переменными экземпляра для хранения количества строк, столбцов и двумерного массива для хранения элементов матрицы.</li><li>Реализуйте конструктор для инициализации матрицы с заданным количеством строк и столбцов и установите все элементы в 0.</li><li>Реализуйте метод setValueAt() для установки значения элемента матрицы в указанной позиции.</li><li>Реализуйте метод getValueAt() для получения значения элемента матрицы в указанной позиции.</li><li>Реализуйте метод multiplyByScalar() для умножения всех элементов матрицы на указанное скалярное значение.</li><li>Реализуйте метод add() для сложения двух матриц.</li><li>Реализуйте метод transpose() для транспонирования матрицы.</li><li>Переопределите операторы “+” и “*” для сложения и умножения матриц соответственно.</li><li>Реализуйте итератор для класса Matrix, чтобы можно было выполнять итерацию по всем элементам матрицы.</li></ol><p>Напишите тестовые примеры JUnit для проверки всех реализованных методов и убедитесь, что они работают правильно.</p><p>Рекомендуется реализовывать каждый метод по одному и тестировать их по мере выполнения, чтобы избежать большой кучи кода, который трудно отлаживать.</p><p>Ответа к этой задаче нет. ChatGPT призналась, что ей как языковой модели это не по зубам. Найдутся ли среди читателей те, кто сможет решить её?</p><p>Как вы считаете, справилась ли ChatGPT с формулировкой задач и их решением? Если нет, то где ошиблась языковая модель?</p><p>Сколько задач их трёх вам удалось решить? Присылайте свои решения на GitHub в комментарии.</p>]]></content:encoded>
    </item>
    <item>
      <title>Алгоритмическая задача про острова</title>
      <link>https://tproger.ru/problems/algoritmicheskaja-zadacha-pro-ostrova</link>
      <comments>https://tproger.ru/problems/algoritmicheskaja-zadacha-pro-ostrova?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Марина Александровна]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/algoritmicheskaja-zadacha-pro-ostrova</guid>
      <description><![CDATA[<p>Решаем алгоритмическую задачу с собеседований про острова несколькими способами: реализация на языках Java и C#.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/algoritmicheskaja-zadacha-pro-ostrova">Алгоритмическая задача про острова</a>»</p>]]></description>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Собеседование]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 29 Jul 2022 12:22:37 GMT</pubDate>
      <content:encoded><![CDATA[<p>Ранее мы разбирали алгоритмическую задачу про острова в <a href="https://tproger.ru/articles/zadachi-s-sobesedovanij-dlja-programmistov/">заданиях с собеседований для программистов</a>. К существующему решению мы получили замечание от нашего пользователя и решили разобраться в сложности алгоритма подробнее.</p><p>Давайте проанализируем выбранный нами вариант и рассмотрим тот, который предложил пользователь Типичного Программиста.</p><ol><li><a href="https://tproger.ru/#part1">Условие</a></li><li><a href="https://tproger.ru/#part2">Решение</a></li><li><a href="https://tproger.ru/#part3">Программный код</a></li><li><a href="https://tproger.ru/#part4">Проверяем решение</a></li><li><a href="https://tproger.ru/#part5">Сложность алгоритма</a></li><li><a href="https://tproger.ru/#part6">Решение от пользователя</a></li></ol><h2>Условие</h2><p>Для двумерного массива M x N, состоящего из единиц, которые обозначают сушу, и нулей, обозначающих воду, верните количество островов.</p><p>Остров окружён водой и образован соединением соседних земель по горизонтали и вертикали. Вы можете предположить, что все четыре края матрицы окружены водой.</p><p>Примечание Если островов нет, возвращаем 0. Помечаем острова через 1, а воду обозначаем как 0.</p><h2>Решение алгоритмической задачи про острова</h2><p>Поиск в глубину — классический подход в решении подобных задач. Его суть заключается в том, что мы проходим по карте и для каждой 1 запускаем поиск в глубину, чтобы осмотреться вправо, влево, вверх и вниз. При каждом запуске поиска в глубину для корневого узла будем увеличивать счётчик с количеством островов.</p><h3>Другими словами</h3><p>Для начала нам нужно найти в матрице хотя бы одну единицу: начинаем построчный обход с нулевого индекса [0,0]. Когда мы находим единицу, помечаем её, как просмотренную, и также просматриваем соседние клетки по направлениям вправо, вниз, влево, вверх.</p><p>Если предыдущая ячейка была сушей, а следующая оказалась водой, мы возвращаемся к суше и просматриваем ячейки по перечисленным направлением в том же порядке.</p><h2>Программный код</h2><p>Напишем код на Java, используя три метода. Включая main, у нас также будет метод обхода острова, чтобы понять, что находится вокруг (есть ли там ещё земля или только вода), а также метод подсчёта островов, в котором и будет запускаться метод обхода.</p><p>Никаких дополнительных инструментов для реализации не нужно. В main пишем статичное расположение островов, но при желании можно поиграться с рандомной подстановкой 0 и 1.</p><h2>Проверяем решение</h2><p>В случае с нашей картой и с учётом того, что по диагонали острова не соединяются, мы должны получить в результате три острова, что и видим на выходе программы:</p><figure><img src="https://media.tproger.ru/uploads/2022/07/Islands-task-Java.jpg" alt="" /></figure><p><a href="https://dotnetfiddle.net/RF0fZY">Здесь</a> вы можете запустить аналгичную программу на C#, а также изменить шаблон карты по своему усмотрению.</p><h2>Сложность алгоритма</h2><p>Сложность решения алгоритмической задачи про острова — O(m*n), где m — количество строк, а n — количество столбцов нашей матрицы.</p><h2>Решение от пользователя</h2><p>Есть вариант более быстрого решения, при котором программа не затормозит в случае большого массива данных:</p><figure><img src="https://media.tproger.ru/uploads/2022/07/Reshenie-algoritmicheskoj-zadachi-pro-ostrova-2.jpg" alt="" /></figure><p>А с каким решением согласны вы? Может, у вас есть своё? Предложите альтернативную реализацию в комментариях.</p>]]></content:encoded>
    </item>
    <item>
      <title>Адовые задачи с собеседований для программистов</title>
      <link>https://tproger.ru/articles/zadachi-s-sobesedovanij-dlja-programmistov</link>
      <comments>https://tproger.ru/articles/zadachi-s-sobesedovanij-dlja-programmistov?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Марина Александровна]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/zadachi-s-sobesedovanij-dlja-programmistov</guid>
      <description><![CDATA[<p>Держите пять непростых задач с интервью для программистов. Большинство из них имеет несколько решений. Предложите своё?</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/zadachi-s-sobesedovanij-dlja-programmistov">Адовые задачи с собеседований для программистов</a>»</p>]]></description>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Собеседование]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 17 Jun 2022 09:03:23 GMT</pubDate>
      <content:encoded><![CDATA[<p>Задачи на собеседованиях для программистов характеризуются видимой сложностью, но если спокойно разобраться, всё решается довольно просто. Мы подготовили несколько заковыристых задач и решения к ним.</p><ol><li><a href="https://tproger.ru/#part1">Алгоритмическая задача про острова</a></li><li><a href="https://tproger.ru/#part2">Поиск знаменитости</a></li><li><a href="https://tproger.ru/#part3">Миллион наименьших чисел</a></li><li><a href="https://tproger.ru/#part4">Сумма чисел</a></li><li><a href="https://tproger.ru/#part5">Тёплые дни: задача на стек</a></li></ol><h2>Алгоритмическая задача про острова</h2><p>Для двумерного массива M x N, состоящего из единиц, которые обозначают сушу, и нулей, обозначающих воду, верните количество островов.</p><p>Остров окружён водой и образован соединением соседних земель по горизонтали и вертикали. Вы можете предположить, что все четыре края матрицы окружены водой.</p><p>Примечание Если островов нет, возвращаем 0.</p><h3>Решение</h3><p>Для начала нам нужно найти в матрице хотя бы одну единицу: начинаем построчный обход с нулевого индекса [0,0]. Когда мы находим единицу, помечаем её, как просмотренную, и также просматриваем соседние клетки по направлениям вправо, вниз, влево, вверх.</p><p>Если предыдущая ячейка была сушей, а следующая оказалась водой, мы возвращаемся к суше и просматриваем ячейки по перечисленным направлением в том же порядке.</p><h3>Код</h3><h2>Поиск знаменитости</h2><p>А эта задача с собеседований встречалась программистам при трудоустройстве в Amazon.</p><p>Дана группа людей из K человек, и эти люди могут знать друг друга, необязательно взаимно. Среди них есть знаменитость. Знаменитость — это человек, который не знает никого в компании, зато каждый из компании знает его. Изначально мы не владеем информацией о том, кто кого знает, но мы можем спросить у каждого участника, знает ли он других людей из группы. Нужно определить знаменитость, используя минимальное количество вопросов.</p><h3>Решение</h3><p>Для начала определимся с тем, что знаменитость всего одна. Чтобы понять следующий алгоритм решения, давайте посмотрим на двух людей из группы. Обозначим их как A и B.</p><figure><img src="https://media.tproger.ru/uploads/2022/06/5507148_account_profile_user_avatar_human_icon.jpg" alt="" /></figure><p>Когда мы спрашиваем у A, знает ли он B, мы получаем два варианта ответа:</p><ol><li>Знает — человек A не знаменитость.</li><li>Не знает — человек B не знаменитость.</li></ol><p>Так, задав всего один вопрос, мы избавляемся от одного кандидата на статус знаменитости. Именно этот алгоритм мы и используем в программе: опрашивается пара человек, после чего один из них вычёркивается из списка, и так пока не останется один кандидат.</p><p>Но наличие одного кандидата ещё не означает, что он знаменитость, ведь её может не быть вовсе. Поэтому последние два действия состоят в том, чтобы спросить у остальных, знают ли они кандидата, а у кандидата — знает ли он всех остальных.</p><h3>Код</h3><h2>Миллион наименьших чисел</h2><p>Опишите алгоритм для нахождения миллиона наименьших чисел в наборе из миллиарда чисел. Память компьютера позволяет хранить весь миллиард чисел.</p><h3>Решение</h3><p>Есть несколько способов решить поставленную задачу:</p><ol><li>Сортировка</li><li>Минимум кучи</li><li>Ранжирование</li></ol><p>Каждый из этих способов мы разобрали в нашей статье по <a href="https://tproger.ru/problems/find-the-smallest-one-million-numbers-in-one-billion-numbers/">нахождению миллиона наименьших чисел</a>.</p><h2>Сумма чисел</h2><p>Такая задача нередко встречается на интервью, и в стрессовой ситуации программист действительно может сразу не сориентироваться.</p><p>Дан отсортированный массив чисел, включая отрицательные, и некое число K. Нужно найти два числа из массива, которые в сумме дадут число K. Если таких чисел нет, в результате возвращаем пустой массив. Если комбинаций чисел, дающих нужную сумму, несколько, возвращаем любую из них.</p><p>Есть несколько вариантов решения задачи:</p><ul><li>перебор всех пар — временная сложность алгоритма O(n²);</li><li>HashSet — O(n);</li><li>бинарный поиск — O(n log n);</li><li>два указателя — O(n).</li></ul><p>Давайте решим задачу с помощью HashSet.</p><p>Примечание Хоть метод HashSet и работает за один проход по массиву, он тратит дополнительную память, так как в худшем случае мы перенесём все элементы из входного массива в наш сет.</p><h3>Решение</h3><p>Создаём пустой сет и смотрим первый элемент массива. Добавляем его в сет. Далее смотрим второй элемент и то, даёт ли он в сумме с вынесенным в сет первым элементом K. Если нет, просто переносим его в сет. Так мы продолжаем до тех пор, пока не найдём число, которое в сумме с другим числом из сета даст число K. Выводим массив из этих двух элементов в качестве ответа.</p><h3>Код</h3><h2>Тёплые дни: задача на стек</h2><p>Дан массив чисел, состоящий из N элементов. Эти числа обозначают температуру в конкретный день. Для каждого дня нужно найти количество суток до наступления более тёплого дня.</p><p>Вот пример того, как это можно изобразить:</p><h3>Решение</h3><p>Используем два цикла. В первом мы будем идти по всем дням, для которых хотим определить ответ, а во втором пробегать направо до тех пор, пока не наткнёмся на более тёплый день.</p><h3>Код</h3><p>Понравились задачки? Держите ещё <a href="https://tproger.ru/articles/10-logicheskih-zadach-s-sobesedovanij-kotorye-zastavjat-zastrelitsja/">десять непростых задач на логику</a>, которые часто задают программистам на собеседованиях.</p>]]></content:encoded>
    </item>
    <item>
      <title>7 логико-математических задач про бегемотов, которые заставят поломать голову</title>
      <link>https://tproger.ru/articles/7-logiko-matematicheskih-zadach-pro-begemotov-kotorye-zastavjat-polomat-golovu</link>
      <comments>https://tproger.ru/articles/7-logiko-matematicheskih-zadach-pro-begemotov-kotorye-zastavjat-polomat-golovu?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Александр Клименков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/7-logiko-matematicheskih-zadach-pro-begemotov-kotorye-zastavjat-polomat-golovu</guid>
      <description><![CDATA[<p>Семь несложных логических и математических задач про разумных цивилизованных бегемотов, которые живут на острове, с объяснениями решений.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/7-logiko-matematicheskih-zadach-pro-begemotov-kotorye-zastavjat-polomat-golovu">7 логико-математических задач про бегемотов, которые заставят поломать голову</a>»</p>]]></description>
      <category><![CDATA[Математика и теория вероятностей]]></category>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Пост пользователя]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 09 Apr 2021 09:19:25 GMT</pubDate>
      <content:encoded><![CDATA[<p>Предлагаю вам для развлечения решить семь несложных логических и математических задач про разумных цивилизованных бегемотов, живущих на острове.</p><h2>1. Интегральное исчисление и мороженое</h2><p>Бегемоты знают интегральное исчисление. Все бегемоты любят мороженое. Какое из следующих утверждений является истинным?</p><ol><li>Бегемоты, которые знают интегральное исчисление, не любят мороженое.</li><li>Все, кто знает интегральное исчисление, любят мороженое.</li><li>Бегемоты, которые любят мороженое, не знают интегральное исчисление.</li><li>Некоторые знатоки интегрального исчисления любят мороженое.</li><li>Интегральное исчисление знают только бегемоты.</li><li>Все знатоки интегрального исчисления не любят мороженое.</li></ol><h2>2. Задача про апельсины</h2><p>Два бегемота съели 100 апельсинов. Первый бегемот потратил на это на 5 часов больше, чем второй, и съел за эти 5 часов 10 апельсинов. Но второй бегемот пожирал апельсины на 50 % быстрее. Сколько времени затратил каждый бегемот на поглощение апельсинов?</p><h2>3. Законы физики в бассейне</h2><p>После плотного перекуса бегемоты отдыхали у бассейна. Они решили устроить конкурс — кто из них самый толстый. Бассейн полон воды и достаточно большой, чтобы в нём поместились все бегемоты разом. Поблизости нет никаких измерительных инструментов. Что вы посоветуете бегемотам?</p><h2>4. Считаем кокосы</h2><p>После купания один из бегемотов задумчиво разглядывал пальмы и считал кокосы. На первой пальме было 11 кокосов, на второй — 16, на третьей — 7, на четвёртой — 21, на пятой вообще не было кокосов, а на шестой выросло целых 34 кокоса. «Какие-то неправильные пальмы», — подумал бегемот. Чем бегемоту не понравились пальмы?</p><h2>5. Задача про апельсиновый сок</h2><p>Устав от созерцания кокосов, бегемот захотел пить и заказал в интернет-магазине 230 литров апельсинового сока. Его доставили вертолётом в одной огромной бочке. Этот сок надо поделить между пятью бегемотами. Как за минимальное количество шагов поделить апельсиновый сок поровну между бегемотами, если у них есть только две ёмкости — 21 и 17 литров?</p><h2>6. Бегемоты программируют на Python</h2><p>Иногда полезно и поработать! Некоторые бегемоты программируют на Python. Все программисты на Python носят шляпы. Какие из следующих утверждений являются истинными:</p><ol><li>Все бегемоты носят шляпы.</li><li>Некоторые из тех, кто носят шляпы, — бегемоты.</li><li>Все те, кто носят шляпы, программируют на Python.</li><li>Все программисты на Python — бегемоты.</li><li>Некоторые бегемоты, которые не программируют на Python, могут носить шляпы.</li><li>Некоторые программисты на Python могут не носить шляпы.</li></ol><h2>7. Лотерея</h2><p>Заработав немного денег, наши бегемоты решили сыграть в лотерею. Лотерейные билеты имеют семизначные номера. Бегемоты решили купить такие билеты, у которых сумма цифр в номере будет равняться их любимому числу — 62. Сколько всего билетов смогут купить бегемоты, если все билеты пока есть в наличии?</p><p>Если хотите ещё немного размять мозги, посмотрите подборку <a href="https://tproger.ru/articles/10-logicheskih-zadach-s-sobesedovanij-kotorye-zastavjat-zastrelitsja/">10 логических задач с собеседований, которые заставят застрелиться</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>15 логических задач с собеседований, которые заставят застрелиться</title>
      <link>https://tproger.ru/articles/10-logicheskih-zadach-s-sobesedovanij-kotorye-zastavjat-zastrelitsja</link>
      <comments>https://tproger.ru/articles/10-logicheskih-zadach-s-sobesedovanij-kotorye-zastavjat-zastrelitsja?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Александр Ланский]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/10-logicheskih-zadach-s-sobesedovanij-kotorye-zastavjat-zastrelitsja</guid>
      <description><![CDATA[<p>Подборка логических задач, которые задают на собеседованиях в Google, Amazon и других IT-компаниях. Разбор решений и подход к каждой задаче.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/10-logicheskih-zadach-s-sobesedovanij-kotorye-zastavjat-zastrelitsja">15 логических задач с собеседований, которые заставят застрелиться</a>»</p>]]></description>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Собеседование]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 21 Feb 2021 08:34:06 GMT</pubDate>
      <content:encoded><![CDATA[<p>Некоторые логические задачи с собеседований вгоняют в недоумение: зачем такое спрашивать? Чтобы создать сложную ситуацию и посмотреть, как быстро вы примете решение. Вопросы на логику при этом отличаются особой заковыристостью, так что сходу сориентироваться бывает сложно.</p><p>• На собеседованиях в IT-компаниях задают логические задачи, чтобы оценить ход мышления, а не конкретные знания
• Задачи делятся на несколько типов: комбинаторные, на поиск противоречий, на оптимизацию и на нестандартное мышление
• Важен не столько правильный ответ, сколько умение рассуждать вслух и структурировать решение
• Большинство задач решаются разбиением на простые шаги — не пытайтесь охватить всё сразу</p><p>Разобраться помогут наши задачи на логику с ответами.</p><h2>Автомат с напитками</h2><p>Начнём с простой логической задачи.</p><p>На склад привезли три машины для напитков. Одна из них выдаёт чай, вторая выдаёт кофе, а третья — чай или кофе (определяется случайно). Любой автомат продаст стакан напитка за одну монету. На каждом автомате приклеена этикетка с выдаваемым напитком. Но на заводе произошла ошибка, из-за чего на всех автоматах наклеены не те этикетки, которые должны быть.</p><p><b>Вопрос: сколько потребуется денег, чтобы определить, где какие автоматы?</b></p><h2>Инопланетяне и десяток храбрецов</h2><p>Такие логические вопросы чаще всего задают на позиции Junior-специалистов.</p><p>В нашу планету вторглась инопланетная раса, чтобы уничтожить всё человечество. Но перед этим они решили дать нам возможность проявить свои интеллектуальные способности. Они отобрали десять умнейших людей планеты, построив их в ряд в полностью тёмной комнате. Каждому они надели чёрную или белую шляпу. После этого свет включился.</p><p>Инопланетянин просит стоящего в конце ряда человека назвать цвет своей шляпы. Если ответ правильный — этот человек остаётся жить, если нет — погибает. Подсмотреть цвет своей шляпы нельзя, однако можно обсудить с остальными определённый принцип ответа, которого будут придерживаться все. Распределение цветов шляп случайное, но вам виден цвет шляп всех остальных людей.</p><p><b>Вопрос: каким должен быть ответ, чтобы в живых осталось как можно больше людей?</b></p><h2>Поездки на мотоциклах</h2><p>У вас есть 50 мотоциклов с полным баком, которого хватает на 100 км езды.</p><p><b>Вопрос: используя все мотоциклы, какое максимальное расстояние вы сможете проехать? Все мотоциклы в начале пути находятся условно в одной точке.</b></p><h2>Что доктор прописал</h2><p>Доктор прописал вам пить две таблетки — одну утром (назовем ее X), а другую вечером (назовем ее Y). Выпить обе или утром, или вечером нельзя. И еще одна загвоздка — таблетки абсолютно одинаковые. И так получилось, что вы доставали таблетки на день, и они перемешались в руке.</p><p><b>Вопрос: как вам выпить таблетки по рецепту доктора и выжить?</b></p><p>P.s. выбросить таблетки нельзя — они стоят миллион.</p><h2>3 лампы и 3 выключателя</h2><p>Эта логическая задача особенно полюбилась на собеседованиях. Есть 2 комнаты. Первая комната закрыта дверью, в ней низкие потолки и висят 3 лампы накаливания. Во второй комнате есть 3 выключателя, подсоединённых к каждой из ламп. Можно как угодно переключать выключатели, но перейти из второй комнаты в первую можно лишь один раз.</p><p><b>Вопрос: как узнать, за какую лампу отвечает каждый из выключателей?</b></p><h2>Два стражника</h2><p>А такая логическая задача часто встречается на интервью от Apple. Игрок дошёл до финального задания в квесте. Перед ним оказались две двери. Первая приведёт к богатству и победе, другая — к поражению. Под дверьми стоит по одному стражнику. Они знают, куда ведут их двери. Но один из них скажет неправду. Неизвестно, кто именно солжёт. Игрок может спросить одного стражника всего один раз.</p><p>Вопрос: что нужно спросить у стража, чтобы выйти к богатству и выиграть квест?</p><h2>Пьяные кролики</h2><p>Как-то раз один наследник захотел убить своего короля, чтобы власть скорей перешла в его руки. У короля была 1000 бутылок вина его любимого сорта. Наследник послал убийцу, чтобы тот отравил любимое вино короля. Но убийцу поймали после того, как он успел отправить лишь одну бутылку. Правитель был умным, поэтому решил использовать десяток кроликов, чтобы определить, куда именно был подсыпан яд. От отравы погибали спустя 1 день.</p><p><b>Вопрос: сколько минимум потребуется времени, чтобы найти отравленную бутылку? Как именно это сделать?</b></p><h2>Полицейский и преступник</h2><p>Полицейский решил наказать заключенного попросил его сделать заявление. Если полицейский посчитает, что узник сказал правду, последнего повесят, а если солгал — застрелят.</p><p><b>Вопрос: какое заключенному нужно сделать заявление, чтобы остаться в живых? </b></p><h2>Голодные белки</h2><p>Данная логическая загадка нередко задаётся на собеседованиях и выделяется среди прочих своей неординарностью. В её решении важны не особые математические способности, а умение абстрагироваться от странного условия. Полюбившаяся интервьюерам задача звучит так: 1,5 белки за 1,5 минуты поедают 1,5 жёлудя.</p><p><b>Вопрос: сколько желудей за 9 минут съедят 9 белок?</b></p><h2>Треугольник муравьёв</h2><p>Есть треугольник с равными углами. На углах стоят по одному муравью. В какой-то момент муравьи начинают идти в другой угол вдоль стороны треугольника. В какой именно — определяется случайно.</p><p><b>Вопрос: каков шанс того, что ни один муравей не столкнётся с другим муравьём?</b></p><h2>10 монет</h2><p>Задача с собеседования в Google.</p><p>Вам завязывают глаза и кладут на стол 10 монет. Вы можете трогать монеты, но на ощупь вы не сможете понять, какой стороной они повернуты вверх. Вам говорят, что пять монет лежат орлом вверх, а другие решкой — других уточнений нет.</p><p><b>Вопрос: можете ли вы сложить монеты в две стопки с одинаковым количеством орлов в каждой? Вы можете подбрасывать монеты любое количество раз.</b></p><h2>Котлета, котлета и ещё одна котлета</h2><p>Логические загадки могут быть очень каверзными. Как, например, эта.</p><p>У вас есть 2 сковородки и 3 котлеты. На приготовление 1 котлеты с одной стороны уходит 1 минута. На одной сковороде вмещается лишь 1 котлета.</p><p><b>Вопрос: за какое минимальное время вы сможете полностью обжарить все 3 котлеты?</b></p><h2>Про перепутанные банки</h2><p>На столе стоят три банки с надписями «Гречка», «Пшенка» и «Смесь. Однако все названия перепутаны.</p><p><b>Вопрос: как найти емкость с гречкой?</b></p><h2>Необычная оплата</h2><p>В поместье пришёл путник. В кармане — ни гроша, лишь одна золотая цепь из 6 звеньев. Хозяин поместья предложил брать плату в виде одного кольца с цепочки за один день проживания, при условии, что будет распилено только одно звено. Хозяин должен получать плату каждый день. Он не хочет принимать предоплату или давать в долг.</p><p><b>Вопрос: как путник должен распилить цепочку, чтобы вносить оплату за жильё каждый день в течение 5 дней?</b></p><h2>Про воду</h2><p>Это задача на логику с собеседования в Microsoft, уже ставшая классикой.</p><p>У вас есть неограниченное количество воды и два ведра — по 3 и 5 литров.</p><p><b>Вопрос: как отмерить ровно 4 литра? </b></p><h2>Часто задаваемые вопросы</h2><h3>Зачем на собеседованиях дают логические задачи?</h3><p>Работодатели используют логические задачи, чтобы оценить аналитическое мышление кандидата и его способность рассуждать в условиях неопределённости. Интервьюеру важно увидеть ход мысли, а не готовый ответ. Такие задачи помогают выявить навыки декомпозиции проблем, которые критичны в повседневной работе разработчика.</p><h3>Как подготовиться к логическим задачам на интервью?</h3><p>Решайте разнообразные головоломки регулярно — хотя бы по одной в день. Тренируйте навык рассуждения вслух: проговаривайте каждый шаг решения. Изучите основные типы задач (комбинаторика, теория вероятностей, оптимизация), чтобы быстро определять подход к новой задаче.</p><h3>Какие логические задачи чаще всего задают в IT-компаниях?</h3><p>Наиболее популярны задачи на комбинаторику (как с кроликами и бутылками), задачи-парадоксы (два стражника), задачи на оптимизацию (котлеты, мотоциклы) и классические головоломки с переливаниями. Google, Amazon и Microsoft особенно любят задачи, где нужно найти нестандартный подход к знакомой ситуации.</p><h3>Нужно ли давать точный ответ на логическую задачу?</h3><p>Нет, точный ответ не всегда обязателен. Интервьюеры ценят структурированный подход к решению: как вы разбиваете задачу на части, какие допущения делаете, как проверяете гипотезы. Даже если финальный ответ неверный, грамотный ход рассуждений может произвести лучшее впечатление, чем угаданный ответ без объяснения.</p><h2>Заключение</h2><p>Решение логических задач — на самом деле не только полезно, но и весело. Даже если вы не собираетесь покорять Google или Microsoft.</p><p>Возможно, вам уже попадались подобные задачки на логику на собеседованиях. Если так, поделитесь своим опытом: что это были за задачки и удалось ли их решить?</p><p>А для любителей поломать голову мы подготовили <a href="https://tproger.ru/quiz/7-logiko-matematicheskih-zadach/">тест на проверку логики и математики</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Задача про обиженного короля и сотню звездочётов</title>
      <link>https://tproger.ru/problems/sad-king-riddle</link>
      <comments>https://tproger.ru/problems/sad-king-riddle?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Туренко]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/sad-king-riddle</guid>
      <description><![CDATA[<p>Король наказывает 100 звездочётов за опоздание, надевая им шляпы. Учёные угадывают цвет шляпы, глядя вперёд. Один рискует, 99 выживают по алгоритму чётности.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/sad-king-riddle">Задача про обиженного короля и сотню звездочётов</a>»</p>]]></description>
      <category><![CDATA[Головоломки]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 23 May 2018 16:22:34 GMT</pubDate>
      <content:encoded><![CDATA[<p>Король после пира в своём дворце дал команду страже арестовать 100 звездочётов, так как они позже всех пришли на празднество и этим его обидели. Он был любителем поиграть и приказал звездочётам выстроиться в ряд, задумав надеть на их головы синие и красные шляпы. После построения им будет запрещено общаться, издавать какие-либо звуки, оглядываться и снимать шляпы. Однако разрешено смотреть на шляпы стоящих спереди и слушать ответы стоящих сзади.</p><p>Король будет подходить к каждому звездочёту и задавать один и тот же вопрос: «какого цвета твоя шляпа?»</p><p>Учёные должны ответить на вопрос короля только одним словом: «красная» или «синяя». Неверный ответ карается тихой смертью, а за верный даруется жизнь (но всё равно придётся стоять безмолвно).</p><p>Король доходчиво объяснил, что в случае нарушения правил будет казнена вся сотня участников его игры. После чего разрешил учёным посовещаться.</p><p>Какой алгоритм поможет спасти максимальное количество звездочётов?</p><p>Обратите внимание Шляпы на головы звездочётов надевает король, обход начинается с конца. Люди выстроены таким образом, что смотрят друг другу в затылок.</p><h2>Решение</h2><p>Звездочёты должны договориться и создать правило: первый отвечающий считает количество синих шляп перед собой, если это нечётное число, он говорит «синяя», если чётное — «красная». Следующий, видя количество и цвет шляп перед собой, может определить, какого цвета шляпа у него на голове (например, если синих все ещё нечётное количество, видимо, на нём красная). Можно вывести правило: если чётный номер говорит «синяя», то синих шляп нечётное число, если он говорит «красная», то красных шляп чётное число и т.д.</p><p>Таким образом гарантированно выживут 99 из 100. У первого шансы 50/50.</p><blockquote>Обратите внимание на другую нашу задачку о том же короле.</blockquote>]]></content:encoded>
    </item>
    <item>
      <title>Задача по проектированию чат-сервера</title>
      <link>https://tproger.ru/problems/engineering-chat-server</link>
      <comments>https://tproger.ru/problems/engineering-chat-server?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Vladimir Gabrinevski]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/engineering-chat-server</guid>
      <description><![CDATA[<p>Как бы вы подошли к проектированию чат-сервера? Предоставьте информацию о компонентах внутренней системы (backend), классах и методах. Перечислите самые трудные задачи, которые необходимо решить.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/engineering-chat-server">Задача по проектированию чат-сервера</a>»</p>]]></description>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 01 Feb 2018 21:36:08 GMT</pubDate>
      <content:encoded><![CDATA[<h3>Условие задачи</h3><p>Как бы вы подошли к проектированию чат-сервера? Предоставьте информацию о компонентах внутренней системы (backend), классах и методах. Перечислите самые трудные задачи, которые необходимо решить.</p><h3>Решение</h3><p>Разработка чат-сервера — огромный проект, команды из многих людей проводят месяцы и годы, пытаясь создать хороший чат-сервер. Вы должны сосредоточиться на отдельном аспекте задачи. Ваше решение не обязано точно отражать реальность, но должно давать хорошее представление о фактической реализации.</p><p>Мы займёмся основными аспектами управления пользователями и организацией общения: добавлением пользователя, созданием беседы, обновлением статуса и т. д. Для экономии времени и места мы не будем углубляться в сетевые аспекты задачи и не будем рассматривать вопросы передачи данных между клиентами и сервером.</p><p>Предполагается, что «дружба» взаимна: вы дружите со мной только в том случае, если и я дружу с вами. Наша чат-система будет поддерживать как групповые, так и приватные беседы. Мы не будем рассматривать голосовой чат, видеочат и пере­дачу файлов.</p><h3>Какие конкретные операции должен поддерживать чат?</h3><p>Мы приведем несколько примеров:</p><ul><li>Вход и выход из чата;</li><li>Добавление запроса (отправка, приём и отклонение);</li><li>Обновление информации о статусе;</li><li>Создание приватных и групповых чатов;</li><li>Добавление новых сообщений в приватные и групповые чаты.</li></ul><p>Это далеко не полный список. Если вам хватит времени, добавьте дополнительные действия.</p><h3>Что можно узнать из этих требований?</h3><p>Необходимо реализовать концепцию пользователей, статуса добавления запроса, статуса подключения и сообщений.</p><h3>Какие базовые компоненты должны присутствовать в системе?</h3><p>Система будет состоять из базы данных, клиентов и серверов. Мы не включаем эти части в объектно-ориентированный проект, но можем обсудить общее видение системы.</p><p>База данных будет использоваться для долгосрочного хранения данных, например списка пользователей и архивов чата. В большинстве случаев подойдет SQL-бaзa данных, но, если нам понадобится большая масштабируемость, можно использовать <a href="https://cloud.google.com/bigtable/">BigTable</a> или другую аналогичную систему. Подробнее вы можете узнать в нашем <a href="https://tproger.ru/tag/db/">разделе</a>, посвящённом базам данных.</p><p>Для обмена данными между клиентами и серверами подойдет XML. Хотя его компактность оставляет желать лучшего, он наиболее удобен для восприятия как человеком, так и компью­тером. Использование XML также упрощает отладку приложения, а это имеет большое значение.</p><p>Примечание переводчика Ещё лучше для передачи данных подойдёт формат <a href="https://tproger.ru/tag/json/">JSON</a>.</p><p>Сервер будет состоять из множества компьютеров. Данные будут распределены между машинами, что требует «переключения» с одного устройства на другое. Возможно, некоторые данные придется перераспределять между машинами. Чтобы сократить время поиска, нужно избегать узких мест. Например, если аутентифика­цией пользователей занимается только одна машина, то её выход из строя закроет доступ к системе миллионам пользователей.</p><h3>Какие основные объекты и методы должны поддерживаться системой?</h3><p>Ключевые объекты нашей системы — пользователи, беседы и сообщения о статусах. Всё это можно реализовать в классе UserManager. Если бы мы уделяли больше вни­мания сетевым аспектам задачи или другим компонентам, вероятно, нам пришлось бы создать для них дополнительные объекты.</p><p>Метод receivedAddRequest класса User оповещает пользователя В о том, что пользо­ватель А запросил добавление его в список контактов. Пользователь В соглашается или отклоняет запрос (при помощи UserManager.approveAddRequest или rejectAddRequest), а класс UserManager обеспечивает добавление пользователей в списки контактов двух пользователей.</p><p>Метод sentAddRequest класса User вызывается UserManager для добавления AddRequest в список запросов пользователя А. Поэтому последовательность операций должна выглядеть так:</p><ol><li>Пользователь А нажимает кнопку «добавить пользователя» в клиентской программе, запрос отправляется на сервер.</li><li>Пользователь В вызывает requestAddUser(User В).</li><li>Этот метод вызывает UserManager.addUser.</li><li>UserManager вызывает методы UserA.sentAddRequest и UserB.receivedAddRequest.</li></ol><p>Это всего лишь один из возможных способов проектирования подобных взаимо­действий, но не единственный и даже не самый лучший.</p><p>Класс Conversation реализован как абстрактный, потому что все экземпляры Conversation должны относиться либо к классу GroupChat, либо к классу PrivateChat, а каждый из этих классов обладает собственной функциональностью.</p><p>Классы AddRequest и UserStatus — простые классы с минимальной функциональ­ностью. Их основное назначение — группировка данных, используемых другими классами.</p><h3>Какие проблемы окажутся самыми трудными (или интересными)?</h3><p>Попробуйте ответить на следующие вопросы:</p><p>Как определить активных пользователей?</p><p>Подключённый пользователь — не всегда активный пользователь. Если сеанс не был корректно завершён, сессия может «зависнуть», расходуя ресурсы сервера и искажая реальное количество активных пользователей. Как с достаточно большой точностью определить активность пользователей?</p><p>Что делать с информационными конфликтами?</p><p>Часть информации должна храниться в оперативной памяти, а часть — в базе данных. Что случится, если синхронизация между ними будет нарушена? Какую информацию считать правильной?</p><p>Что делать с возрастающим количеством пользователей?</p><p>Как на этапе проектирования заложить многократное увеличение количества пользователей?</p><p>Как защититься от DоS-атак?</p><p>Клиенты могут передавать данные на сервер, но что, если сервер попытаются «завалить» по­током запросов? Как предотвратить атаку?</p>]]></content:encoded>
    </item>
    <item>
      <title>Построить алгоритм выбора случайного элемента из последовательности, чтобы каждый элемент мог оказаться выбранным с равной вероятностью</title>
      <link>https://tproger.ru/problems/rand-element-sequence</link>
      <comments>https://tproger.ru/problems/rand-element-sequence?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Оля Пестерева]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/rand-element-sequence</guid>
      <description><![CDATA[<p>Алгоритм выбирает элемент с равной вероятностью за один проход, используя O(1) дополнительной памяти и единственный итератор без создания нового.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/rand-element-sequence">Построить алгоритм выбора случайного элемента из последовательности, чтобы каждый элемент мог оказаться выбранным с равной вероятностью</a>»</p>]]></description>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Математика и теория вероятностей]]></category>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Собеседование]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 17 Feb 2017 11:03:05 GMT</pubDate>
      <content:encoded><![CDATA[<p>Пусть у нас есть некоторая конечная последовательность чисел и мы имеем итератор, указывающий на первый элемент. Мы можем при помощи итератора посмотреть значение текущего элемента и перейти к следующему элементу. Требуется построить такой алгоритм выбора случайного элемента из этой последовательности, чтобы каждый элемент мог оказаться выбранным с равной вероятностью.</p><p>Ограничения: мы можем использовать O(1) дополнительной памяти и не можем создавать новый итератор. Можно пользоваться функцией генерации случайного числа от [0;1).</p><h3>Решение:</h3><p>Создадим некоторую переменную, обозначим ее — x. Будем идти по последовательности и по ходу хранить номер элемента последовательности. Пусть мы сейчас находимся на элементе номер i, нумерация с 1. С вероятностью 1/i присвоим переменной x значение текущего элемента. Чтобы сделать действие с вероятностью p можем сгенерировать случайное число в диапазоне [0;1) и если сгенерированное число меньше p, то делаем действие, иначе не делаем.</p><h3>Почему это работает?</h3><p>Осталось доказать несложное утверждение: в переменной x после выполненных действий может оказаться любой элемент последовательности равновероятно, то есть каждый с вероятностью 1/n, где n число элементов последовательности.</p><h3>Доказательство:</h3><p>Будем доказывать по индукции. Для n=1 утверждение очевидно. Предположим, что утверждение верно для n=k, докажем его для n=k+1. После того, как мы выполним указанные действия для k первых элементов в переменной x находится одно из k чисел равновероятно, то есть с вероятностью 1/k каждое, по предположению индукции. После обработки (k+1)-го элемента вероятность того что в переменной x находится (k+1)-й элемент – 1/(k+1). Следовательно, вероятность того что в переменной x находится не (k+1)-й элемент – k/(k+1), а поскольку все k первых элементов были сохранены в переменной x равновероятно до обработки (k+1)-го элемента, то вероятность появления в переменной x любого из первых k элементов 1/(k+1). Таким образом утверждение доказано.</p><p>Если вам понравилась эта задачка, возможно, вам также понравится:</p><ul><li>Вы должны выбрать одну из двух ставок. При первом варианте вы должны забросить баскетбольный мяч в корзину. Если попадёте, то получите 50 тыс. рублей. Во втором варианте вам надо попасть два раза из трёх бросков, и тогда вы также получите те же 50 тыс. рублей. Какой из этих вариантов вы предпочтёте?<br />Разбор решения</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>123 задачи с IT-собеседований с разбором решений</title>
      <link>https://tproger.ru/articles/problems</link>
      <comments>https://tproger.ru/articles/problems?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Картофельный Повелитель]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/problems</guid>
      <description><![CDATA[<p>Подборка из 123 задач с IT-собеседований с разбором решений. Логика, алгоритмы, программирование.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/problems">123 задачи с IT-собеседований с разбором решений</a>»</p>]]></description>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Стеки и очереди]]></category>
      <category><![CDATA[Поразрядная обработка]]></category>
      <category><![CDATA[Сортировка и поиск]]></category>
      <category><![CDATA[C++]]></category>
      <category><![CDATA[Рекурсия и динамика]]></category>
      <category><![CDATA[Головоломки]]></category>
      <category><![CDATA[Математика и теория вероятностей]]></category>
      <category><![CDATA[Задачи умеренной сложности]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Оптимизация]]></category>
      <category><![CDATA[Собеседование]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 20 Oct 2015 12:45:48 GMT</pubDate>
      <content:encoded><![CDATA[<p>При приеме сотрудника в офис на должность программиста, работодатель испытывает кандидата не только вопросами о навыках, но и всевозможными логическими задачами, IT-кейсами и заданиями по разработке для профессиональных программистов. Как правило, список этих задач у работодателей совпадает, а значит, мы можем подготовиться к любому собеседованию!</p><p><b>Ключевые выводы</b>
• На IT-собеседованиях встречаются логические, алгоритмические задачи, вопросы по языкам и Fermi-задачи
• Ключ к успеху — умение рассуждать вслух
• Важно практиковаться на разных типах задач
• Задачи давались в Google, Amazon, Apple и Twitter</p><p>В нашей <a href="https://tproger.ru/problems/">рубрике c заданиями</a> уже больше 100 вопросов с подробным разбором решений. Мы решили собрать воедино все самые интересные и популярные задачи для программистов, которые могут встретиться вам на собеседовании.</p><h2>Задачи на структуры данных</h2><p>Есть однонаправленный список из структур. В нём random указывает на какой-то еще элемент этого же списка. Требуется написать функцию, которая копирует этот список с сохранением структуры (т.е. если в старом списке random первой ноды указывал на 4-ю, в новом списке должно быть то же самое – рандом первой ноды указывает на 4-ю ноду нового списка). O(n), константная дополнительная память + память под элементы нового списка. Нельзя сразу выделить память под все данные одник куском т.е. список должен быть честным, разбросанным по частям, а не единым блоком, как массив.</p><p>Ответ Вариант реализации</p><p>Классическая задачка с собеседований в Google. На доске записаны числа, вам нужно ответить на вопрос: какое число идёт дальше?</p><p>Ответ</p><p>Допустим, вы летите из Москвы во Владивосток, а затем обратно, при полном безветрии. Затем вы совершаете точно такой же перелёт, но на этот раз на протяжении всего перелёта дует постоянный западный ветер: в одну сторону попутный, в обратную — лобовой.</p><p>Ответ</p><p>Что не так в этом отрывке кода на С++?</p><p>Ответ</p><p>Задача, которая была популярна в своё время на собеседованиях в Amazon. Мы русифицировали её, но смысл остался тот же. Вам нужно продолжить последовательность.</p><p>Ответ автора с обзором вариантов ответов подписчиков</p><p>Как это вычислить, не пользуясь калькулятором? Можете дать приблизительный ответ?</p><p>Ответ</p><p>«Вас уменьшили до размеров 5-центовой монеты и бросили в блендер. Ваш вес уменьшился так, что плотность вашего тела осталась прежней. Лезвия начнут вращаться через 60 секунд. Ваши действия?»</p><p>Это классическая google-задачка, хороший разбор которой в рунете не так-то просто найти. Мы подготовили его для вас. Абсолютного правильного ответа нет, но есть те, которые явно лучше остальных.</p><p>Разбор вариантов ответа</p><p>Вопрос по С++. Что за ошибка «pure virtual function call»? В какой ситуации она может быть сгенерирована? Предоставьте минимальный код, приводящий к ней.</p><p>Ответ</p><p>В вашем распоряжении 10 тысяч серверов в дата-центре с возможностью удалённого управления и один день, чтобы получить миллион долларов. Что вы для этого сделаете?</p><p>Ответ</p><p>У вас есть аналоговые часы с секундной стрелкой. Сколько раз в день все три стрелки часов накладываются друг на друга?</p><p>Ответ</p><p>В чём разница между string и String в C#?</p><p>Ответ</p><p>Вы играете в футбол на пустынном острове и хотите подбросить монетку, чтобы решить, какой команде достанется мяч. Единственная монета, что у вас есть, является гнутой, и поэтому вносит явные искажения в результат при подбрасывании. Как вы тем не менее можете использовать такую монету, чтобы принять справедливое решение?</p><p>Ответ</p><p>Cколько мячей для гольфа войдет в школьный автобус?</p><p>Для справки: в Национальных стандартах транспотрных средств для школ в США на 1995 год указаны максимальные размеры школьного автобуса и равны 40 футам в длину и 8.5 футам в ширину. Стандартный диаметр мяча для гольфа — 1.69 дюйма с допуском 0.005 дюймов.</p><p>Ответ</p><p>Представьте себе вращающийся диск, например DVD. У вас есть в распоряжении черная (Ч) и белая (Б) краски. На краю диска установлен небольшой датчик, который определяет цвет под ним и выдает результат в виде сигнала. Как бы вы раскрасили диск, чтобы было возможно определить направление вращения по показаниям датчика?</p><p>Дадим небольшое пояснение к задаче. Первое, что нужно иметь ввиду, это то, что нельзя наблюдать за самим диском. Например, вы сидите в офисе, а диск вращается в закрытой лаборатории. Единственная возможность определить направление вращения — использовать оцифрованные показания датчика, и ничего больше.</p><p>Датчик фиксирует цвет точки в непосредственном месте установки в последовательные моменты времени. Показания представляются в виде «ЧЧЧББ…». Задача сводится к такой раскраске диска, где последовательность показаний отличается при вращении в прямую и в противоположную стороны.</p><p>Ответ</p><p>У вас есть исходный код приложения на языке С, которое аварийно завершается после запуска. После десяти запусков в отладчике вы обнаруживаете, что каждый раз программа падает в разных местах. Приложение однопоточное и использует только стандартную библиотеку С. Какие ошибки могут вызвать падение приложения? Как вы проверите каждую?</p><p>Ответ</p><p>Найдите ошибки в следующем коде.</p><p>Ответ</p><p>Объясните, что делает этот код.</p><p>((n &amp; (n – 1)) == 0)</p><p>Ответ</p><h2>Задачи на логику и математику</h2><p>Дано 100-этажное здание. Если яйцо сбросить с высоты N-го этажа (или с большей высоты), оно разобьется. Если его бросить с любого меньшего этажа, оно не разобьется. У вас есть два яйца. Найдите N за минимальное количество бросков.</p><p>Ответ</p><p>Продолжаем задачки по С/С++. Что означает ключевое слово volatile и в каких ситуация оно может быть применено? Если даже помните формальное значение, попробуйте привести пример ситуации, где volatile на самом деле будет полезно.</p><p>Ответ</p><p>У вас есть отсортированная матрица размера MxN. Предложите алгоритм поиска в ней произвольного элемента. Под отсортированной матрицей будем понимать такую матрицу, строки и столбцы которой отсортированы (см. пример).</p><p>Ответ</p><p>Напишите метод, находящий максимальное из двух чисел, не используя операторы if-else или любые другие операторы сравнения.</p><p>Ответ</p><p>На пустынном шоссе вероятность появления автомобиля за 30-минутный период составляет 0.95. Какова вероятность его появления за 10 минут?</p><p>Ответ</p><p>Напишите функцию суммирования двух целых чисел без использования «+» и других арифметических операторов.</p><p>Ответ</p><p>У вас есть парк из 50 грузовиков. Каждый из них полностью заправлен и может проехать 100 км. Как далеко с их помощью вы можете доставить определенный груз? Что будет, если в вашем распоряжении N грузовиков?</p><p>Не все понимают сразу о чем речь: территориально это место, где нет никаких заправочных станций. Единственное место, где можно здесь найти горючее – это топливные баки грузовиков. Пересесть из грузовика в гибридный легковой автомобиль Prius нельзя. Бросить грузовик без топлива, где бы это ни случилось, и без водителя – в порядке вещей. И единственное, что здесь важно, – доставить как можно дальше ценный груз.</p><p>Ответ</p><p>Опишите алгоритм для нахождения миллиона наименьших чисел в наборе из миллиарда чисел. Память компьютера позволяет хранить весь миллиард чисел. Если придумали какое-либо решение, то оцените его эффективность по времени. Есть ли более эффективное решение?</p><p>Ответ</p><p>Напишите метод, который будет подсчитывать количество цифр «2», используемых в десятичной записи целых чисел от 0 до n (включительно). Картинка дана в качестве подсказки к одному из возможных решений.</p><p>Ответ</p><p>Где вы будете плыть быстрее — в воде или сиропе?</p><p>Это классическая задача с долгой историей, которую обсуждал в своё время еще Исаак Ньютон. Когда-то она использовалась и на IT-собеседованиях в Google (сейчас — <a href="http://habrahabr.ru/post/184008/">нет</a>). Тем не менее предлагаем вам порассуждать над решением.</p><p>Ответ</p><p>Напишите методы для умножения, вычитания и деления целых чисел, используя из арифметических операций только оператор суммирования. Язык реализации не важен, об оптимизации скорости работы и использования памяти также можете не особо беспокоиться. Главное, что можно использовать только сложение. В подобных задачах полезно вспомнить суть математических операций.</p><p>Ответ</p><p>Допустим, вы пишете конвейер, в котором 2 потока, используя общий буфер, обрабатывают данные. Поток-producer эти данные создает, а поток-consumer их обрабатывает (Producer–consumer problem). Следующий код представляет собой самую простую модель: с помощью std::thread мы порождаем поток-consumer, a создавать данные мы будем в главном потоке.</p><p>Опустим механизмы синхронизации двух потоков, и обратим внимание на функцию main(). Попробуйте догадаться, что с этим кодом не так, и как его исправить?</p><p>Ответ</p><p>Дано 20 баночек с таблетками. В 19 из них лежат таблетки весом 1 г, а в одной – весом 1.1 г. Даны весы, показывающие точный вес. Как за одно взвешивание найти банку с тяжелыми таблетками?</p><p>Ответ</p><p>Дана шахматная доска размером 8×8, из которой были вырезаны два противоположных по диагонали угла, и 31 кость домино; каждая кость домино может закрыть два квадратика на поле. Можно ли вымостить костями всю доску? Дайте обоснование своему ответу.</p><p>Ответ</p><p>Дан входной файл, содержащий четыре миллиарда целых 32-битных чисел. Предложите алгоритм, генерирующий число, отсутствующее в файле. Имеется 1 Гбайт памяти для этой задачи. Дополнительно: а что если у вас всего 10 Мбайт? Количество проходов по файлу должно быть минимальным.</p><p>Ответ</p><p>Предложите алгоритм, генерирующий все корректные комбинации пар круглых скобок. Под корректными комбинациями пар будем понимать правильно открытые и закрытые скобки. На вход подаётся число пар скобок, на выходе должны быть все возможные их комбинации в виде набора строк.</p><p>Ответ</p><p>Вы поставили стакан воды на диск проигрывателя виниловых пластинок и медленно увеличиваете скорость вращения. Что произойдет раньше: стакан сползет в сторону, стакан опрокинется, вода расплескается?</p><p>Этот вопрос задавали ранее на собеседованиях в Apple. При ответе рассмотрите возможные варианты и укажите, от чего зависит ответ, если их несколько.</p><p>Ответ</p><p>Короткая задачка по С++ в виде вопроса для новичков. Почему деструктор полиморфного базового класса должен объявляться виртуальным? Полиморфным считаем класс, в котором есть хотя бы одна виртуальная функция.</p><p>Ответ</p><p>Напишите функцию, меняющую местами значения переменных, не используя временные переменные. Предложите как можно больше вариантов.</p><p>Ответ</p><h2>Задачи на алгоритмы</h2><p>Предложите алгоритм поиска в односвязном списке k-го элемента с конца. Список реализован вручную, есть только операция получения следующего элемента и указатель на первый элемент. Алгоритм, по возможности, должен быть оптимален по времени и памяти.</p><p>Ответ</p><p>Напишите функцию, определяющую количество битов, которые необходимо изменить, чтобы из целого числа А получить целое число B. Числа, допустим, 32-битные, язык любой.</p><p>Это одна из типичных задач на работу с битами, которые любят давать на собеседовании. Если вы никогда с ними не сталкивались, вам будет сложно сразу решить задачу с учётом стрессовой ситуации, поэтому запомните использованные при решении трюки.</p><p>Ответ</p><p>В книге N страниц, пронумерованных как обычно от 1 до N. Если сложить количество цифр, содержащихся в каждом номере страницы, будет 1095. Сколько страниц в книге?</p><p>Ответ</p><p>Задачка по С++, которая, тем не менее, будет полезна и для других языков. Сопоставьте хэш-таблицу и mар из стандартной библиотеки шаблонов (STL). Как организована хэш-таблица? Какая структура данных будет оптимальной для небольших объемов данных?</p><p>Ответ</p><p>Разработайте класс, обеспечивающий блокировку так, чтобы предотвратить возникновение <a href="https://ru.wikipedia.org/wiki/%D0%92%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%B0%D1%8F_%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0">мертвой блокировки</a>.</p><p>Ответ</p><p>Напишите функцию на С++, выводящую в стандартный поток вывода K последних строк файла. При этом файл очень большой, допустим 50 ГБ, длина каждой строки не превышает 256 символов, а число K &lt; 1000.</p><p>Ответ</p><p>Дан кусок сыра в форме куба и нож. Какое минимальное количество разрезов потребуется сделать, чтобы разделить этот кусок на 27 одинаковых кубиков? А на 64 кубика? После каждого разреза части можно компоновать как угодно.</p><p>Такую задачку раньше часто давали на собеседованиях, а придумана она была ещё в 1950 году.</p><p>Ответ</p><p>Реализуйте метод, определяющий, является ли одна строка перестановкой другой. Под перестановкой понимаем любое изменение порядка символов. Регистр учитывается, пробелы являются существенными.</p><p>Ответ</p><p>В тёмной комнате вам вручают колоду карт, в которой известное количество карт N лежат рубашкой вверх, а остальные — вниз. Вы не можете видеть карты, но можете их переворачивать. Как вы разделите колоду на две стопки, чтобы в каждой из них было одинаковое число карт, лежащих рубашкой вверх?</p><p>Эта головоломка в своё время была популярна в JP Morgan Chase. Понятное дело, оказавшись в темноте, вы просто достанете сотовый телефон и воспользуетесь экраном как фонариком. Однако эта задачка появилась до эпохи сотовых телефонов, и её можно решить, даже не видя карт.</p><p>Ответ</p><p>Реализуйте вручную стек со стандартными функциями push/pop и дополнительной функцией min, возвращающей минимальный элемент стека. Все эти функции должны работать за O(1). Решение оптимизируйте по использованию памяти.</p><p>Ответ</p><p>У скольких целых чисел, лежащих в диапазоне от 1 до 1000, есть цифра 3? Посчитать нужно без использования компьютера, приведя свои рассуждения в комментариях.</p><p>Ответ</p><p>У вас есть много URL-адресов, порядка 10 миллиардов. Как бы вы организовали эффективный поиск дубликатов, учитывая, что все они, конечно же, не поместятся в памяти?</p><p>Ответ</p><p>Вы должны выбрать одну из двух ставок. При первом варианте вы должны забросить баскетбольный мяч в корзину за один бросок. Если попадёте, то получите 50 тыс. рублей. Во втором варианте вам надо попасть два раза из трёх бросков, и тогда вы также получите те же 50 тыс. рублей. Какой из этих вариантов вы предпочтёте? Будет ли ваше умение забрасывать мячи влиять на выбор?</p><p>Ответ</p><p>Представьте себе треугольник, составленный из чисел. Одно число расположено в вершине. Ниже размещено два числа, затем три, и так до нижней грани. Вы начинаете на вершине, и нужно спуститься к основанию треугольника. За каждый ход вы можете спуститься на один уровень и выбрать между двумя числами под текущей позицией. По ходу движения вы «собираете» и суммируете числа, которые проходите. Ваша цель — найти максимальную сумму, которую можно получить из различных маршрутов.</p><p>Какой алгоритм вы предложите? Какая у него будет сложность и можно ли предложить лучший вариант?</p><p>Ответ</p><p>Даны два слова или фразы, и ваша задача — проверить, являются ли они анаграммами.</p><p>Анаграмма — это игра со словами, когда в результате перестановки букв слова или фразы получаем другое слово или фразу. Два слова являются анаграммами, если мы можем получить одно из другого переставляя буквы местами.</p><p>Ответ</p><p>Предложите алгоритм, который обнуляет столбец N и строку M матрицы, если элемент в ячейке (N, M) нулевой. Конечно же, нужно минимизировать затраты памяти и время работы.</p><p>Ответ</p><p>Разработайте алгоритм, обнаруживающий в массиве все пары целых чисел, сумма которых равна заданному значению.</p><p>Ответ</p><p>Предположим, вам нужно разработать алгоритм, демонстрирующий круг знакомств человека для социальных сетей. Как бы вы это сделали, при условии, что база очень большая?</p><p>Под большой базой подразумевается порядка миллиарда зарегистрированных пользователей и не менее 100 миллиардов «дружеских» связей между ними.</p><p>Ответ</p><h2>Задачи на графы и списки</h2><p>Допустим, у вас есть однонаправленный список с петлёй. Его «последний» элемент содержит указатель на один из элементов этого же списка, причём не обязательно на первый. Ваша задача — найти начальный узел петли.</p><p>Элементы списка менять нельзя, память можно использовать только константную.</p><p>Ответ</p><p>На острове существует правило — голубоглазые люди не могут там находиться. Самолет улетает с острова каждый вечер в 20:00. Все жители собираются за круглым столом ежедневно, каждый человек может видеть цвет глаз других людей, но не знает цвет собственных. Никто не имеет права сказать человеку, какой у него цвет глаз. На острове находится не менее одного голубоглазого человека. Сколько дней потребуется, чтобы все голубоглазые уехали?</p><p>Ответ</p><p>Напишите код, удаляющий дубликаты из несортированного связного списка. Можно использовать только константную память.</p><p><a></a></p><p>Ответ</p><p>Напишите метод, тасующий карточную колоду. Колода должна быть идеально перемешана т.е. перестановки карт должны быть равновероятными. Вы можете использовать идеальный генератор случайных чисел.</p><p>Ответ</p><p>Допустим, вам поручили задачу по разработке поискового робота — программы, которая, грубо говоря, посещает страницы в Интернете, индексирует, выделяет из них ссылки, переходит по ним и повторяет процесс. Вопрос: как избежать зацикливания?</p><p>Ответ</p><p>У вас есть стеклянный кувшин, в котором лежат небольшие шарики, и вы в любое время можете определить их количество. Вы со своим другом играете в следующую игру: каждый из вас по очереди забирает из кувшина 1 или 2 шарика. Игрок, который забирает последний шарик, выигрывает. Какая самая лучшая стратегия в этой игре? Можете ли вы в самом начале предсказать, кто выиграет?</p><p>Ответ</p><p>Имеется N компаний, и вы хотите, чтобы они слились и образовали одну крупную компанию. Сколько разных способов вы можете использовать для этого? Поглощение можно считать частным случаем слияния, когда А поглощает Б и Б полгощает А — два разных способа. Равнозначные слияния тоже возможны.</p><p>Ответ</p><p>Какой минимальный комплект монет необходим для того, чтобы выдать любую сдачу от 1 до 99 центов? Доступные номиналы монет: 1, 5, 10, 25, 50 центов и 1 доллар.</p><p>Ответ</p><p>У вас есть 25 лошадей. Сколько забегов вам нужно устроить, чтобы определить трех самых быстрых из них? Вы не можете пользоваться секундомером. В каждом заезде могут участвовать только пять лошадей.</p><p>Ответ</p><p>Короткая задачка на сообразительность. По результатам исследования известно, что 70% людей любят кофе, в то же время 80% любят чай. Каковы верхние и нижние границы доли людей, которые одновременно любят кофе и чай?</p><p>Ответ</p><p>Задачка, которую нужно решать без калькулятора и компьютера, имея под рукой только карандаш и бумагу. Сколько нулей в конце факториала 100?</p><p>Ответ</p><p>Предложите алгоритм нахождения самой большой суммы непрерывной последовательности из массива целых чисел, как положительных, так и отрицательных.</p><p>Ответ</p><p>Напишите программу расчета значения медианы в потоке чисел, динамически отслеживающую новые поступающие числа, получаемые рандомом.</p><p>Ответ</p><p>Идет дождь, а вам надо добраться до вашей машины, которая стоит в самом дальнем конце парковки. Побежите ли вы к ней или нет, если ваша цель — как можно меньше промокнуть? Как вы будете себя вести, если у вас есть зонтик?</p><p>Ответ</p><p>Представьте, что существует квадратная матрица, каждый пиксель которой может быть черным или белым. Разработайте алгоритм поиска максимального субквадрата, у которого все стороны черные.</p><p>Разбор <a href="https://tproger.ru/problems/max-black-bordered-submatrix/">двух вариантов решения</a> за O(N^4) и O(N^3). Можете ли вы найти другие варианты?</p><p>Ответ</p><p>Предположим, в некоторый бар ходят только необщительные посетители. Вдоль барной стойки расположены 25 мест. Всякий раз, когда входит новый посетитель, он обязательно садится на самое дальнее, насколько это возможно, место от остальных гостей. Ни один не сядет рядом с кем-то другим: если посетитель входит и видит, что «свободных» мест нет, он тут же разворачивается и уходит из бара. Бармену, естественно, хочется, чтобы за стойкой сидело как можно больше клиентов. Если ему разрешено усадить первого посетителя на любое место, куда выгоднее его посадить с точки зрения бармена?</p><p>Ответ</p><p>Опишите, как можно использовать один одномерный массив для реализации трех стеков.</p><p>Ответ</p><p>У вас есть неограниченное количество монет достоинством 25, 10, 5 и 1 цент. Напишите код, определяющий количество способов представления n центов.</p><p>Ответ</p><p>Напишите код, который позволяет найти минимальное расстояние (выражаемое количеством слов) между любыми двумя словами в файле. Порядок не важен.</p><p>Достаточно ли будет линейного времени?<br />Сколько памяти понадобится для решения?</p><p>Ответ</p><p>Смоделируйте использование игральной кости с семью гранями, если в вашем распоряжении имеется только кость с пятью гранями.</p><p>Иными словами, как получить случайное число в диапазоне от 1 до 7, используя генератор случайных целых чисел от 1 до 5?</p><p>Ответ</p><h2>Задачи на строки и массивы</h2><p>Напишите код, разбивающий связный список вокруг некоторого значения так, чтобы все меньшие узлы оказались перед узлами, большими или равными этому значению.</p><p>Ответ</p><p>Напишите метод, генерирующий случайную последовательность m целых чисел из массива размером n. Все элементы выбираются с одинаковой вероятностью.</p><p>Первое, что приходит в голову, — выбрать случайные элементы из массива и поместить их в новый массив. Но что если мы выберем один и тот же элемент дважды?</p><p>Ответ</p><p>Представьте себе робота, находящегося в левом верхнем углу сетки с координатами (X, Y). Робот может перемещаться в двух направлениях: вправо и вниз. Сколько существует маршрутов, проходящих от точки (0, 0) до точки (X, Y)?</p><p>Дополнительно предположите, что на сетке существуют области, которые робот не может пересекать. Разработайте алгоритм построения маршрута от левого верхнего до правого нижнего угла.</p><p>Ответ</p><p>Реализуйте метод сжатия строки на основе счетчика повторяющихся символов. Например, строка aabcccccaaa должна превратиться в а2b1с5аЗ. Если «сжатая» строка оказывается длиннее исходной, метод должен вернуть исходную строку.</p><p>Ответ</p><p>Вы находитесь в автомобиле, где к полу веревочкой привязан шар, наполненный гелием. Окна закрыты. Вы нажимаете на педаль газа. Что произойдет с шаром: переместится он вперед, назад или останется в прежнем положении?</p><p><a></a></p><p>Ответ</p><p>Задачка, на примере который можно кратко ознакомиться с основами RSA-криптографии.</p><p>Допустим, вы хотите удостовериться, что у вашего друга Пети есть номер вашего телефона. Но вы не можете спросить его об этом прямо. Вам придется написать ему сообщение на карточке и отдать карточку Кате, которая будет выступать в качестве посредника. Катя отнесет карточку Пете, он напишет свое сообщение и отдаст его Кате, которая передаст его вам. Вы не хотите, чтобы Катя узнала ваш номер телефона. Как в таких обстоятельствах следует сформулировать свой вопрос Пете?</p><p>Даже не зная ничего про RSA можно попробовать придумать ответ.</p><p>Ответ</p><p>Задача на знание конкретных языков. Объясните разницу между шаблонами в C++ и дженериками в Java.</p><p>Многие программисты полагают, что шаблоны C++ и дженерики (например в Java) — это одно и то же, ведь их синтаксис похож: в обоих случаях можно написать что-то вроде List&lt;T&gt;. Но различия на самом деле есть.</p><p>Ответ</p><p>Реализуйте вручную «умный» указатель с автоматическим управлением памятью на C++.</p><p>Умный (интеллектуальный) указатель — это тот же обычный указатель, обеспечивающий безопасность благодаря автоматическому управлению памятью. Такой указатель помогает избежать множества проблем: «висячие» указатели, «утечки» памяти и отказы в выделении памяти. Интеллектуальный указатель должен подсчитывать количество ссылок на указанный объект.</p><p>На первый взгляд эта задача кажется довольно сложной, особенно если вы не эксперт в C++.</p><p>Ответ</p><p>Эта головоломка, в которой вас пытаются запутать, предложив поменять свое решение, известна также под именем «Парадокс Монти Холла». Монти Холл был первым ведущим телевизионной игры-шоу «<a href="https://en.wikipedia.org/wiki/Let%27s_Make_a_Deal">Давайте заключим сделку</a>»</p><p>Перед вами три коробки, в одной из которых находится ценный приз, в двух других ничего нет. Вы можете выбрать любую коробку, но вам по-прежнему неизвестно, в какой именно приз. Одну из двух не выбранных вами коробок открывают и показывают, что она пустая. Теперь вы можете или оставить коробку, которую вы первоначально выбрали (оставить), или поменять ее на другую, неоткрытую (заменить). Что вы предпочтете сделать (оставить или заменить)?</p><p>Ответ</p><p>У вас есть пустое помещение и группа людей снаружи. За один ход вы можете либо позволить одному человеку войти в помещение, либо выпустить из него одного человека. Можете ли вы предложить серию ходов, при которой каждая возможная комбинация людей находится в помещении только один раз?</p><p>Нужно время, чтобы понять, чего именно хочет от вас интервьюер. Разобраться в этом помогает простой пример. Скажем, за порогом находятся два человека, Ларри и Сергей. Возможны четыре комбинации их присутствия в комнате, учитывая тот случай, когда в комнате вообще никого нет.</p><p>Вот они:</p><ul><li>В помещении никого нет.</li><li>В помещении только Ларри.</li><li>В помещении только Сергей.</li><li>В помещении Ларри и Сергей.</li></ul><p>Вопрос заключается в том, можем ли мы начать с того, что в комнате никого нет, а затем пройти указанную последовательность шагов?</p><p>Иными словами, как сгенерировать неповторяющиеся комбинации, меняя только один элемент за раз?</p><p>Ответ</p><p>Напишите код поиска субматрицы с максимально возможной суммой в матрице N*N, содержащей положительные и отрицательные числа.</p><p>Ответ</p><p>Сложная задача, требующая умения придумывать алгоритмы.</p><p>По условию требуется разработать алгоритм, позволяющий найти k-e число из упорядоченного числового ряда, в разложении элементов которого на простые множители присутствуют только 3, 5 и 7.</p><p>Решение с примерами кода на Java есть у нас на сайте.</p><p>Решение с примерами кода</p><p>Дан список из миллиона слов. Разработайте алгоритм, создающий максимально возможный прямоугольник из букв так, чтобы каждая строка и каждый столбец образовывали слово (при чтении слева направо и сверху вниз). Слова могут выбираться в любом порядке, строки должны быть одинаковой длины, а столбцы — одинаковой высоты.</p><p>Ответ</p><p>Дан массив с числами типа Integer. Вам нужно написать функцию, которая на входе получит исходный массив, а на выходе вернет массив, в котором каждое значение получено путем произведения всех значений исходного массива с отличным от текущего индексом.</p><p>Для ясности приведем пример. Допустим, исходный массив имеет вид:</p><p>Тогда функция должна вернуть:</p><p>Расчет значений происходит следующим образом:</p><p>Дополнительные условия:</p><ul><li>Нельзя использовать деление.</li><li>Функция должна быть с наименьшими затратами памяти и времени выполнения.</li></ul><p>Ответ</p><h2>Задачи на рассуждение</h2><p>Задача на умение рассуждать. Конкретный ответ не важен, важно показать как вы мыслите. Представьте, что вам необходимо добраться из точки A в точку B, но вы не знаете, как. Как вы будете действовать?</p><p>Ответ</p><p>Представьте, что вам дали задание разработать план эвакуации большого города (в классическом варианте — Сан-Франциско). С чего вы начнете?</p><p>Ответ</p><p>Задача, которую предлагали на собеседованиях в Apple: у вас есть массив с целыми числами, в том числе и отрицательными, вам нужно найти самое большое произведение 3 чисел из этого массива.</p><p>Например: у вас есть массив list_of_ints, содержащий числа -10, -10, 1, 3, 2. Функция, которая обрабатывает этот массив, должна вернуть 300, так как -10 * -10 * 3 = 300. Задание нужно выполнить максимально эффективно, не забывая учесть отрицательные числа.</p><p>Ответ</p><p>Представьте страну, где все родители хотят иметь мальчика. Каждая семья продолжает рожать детей до тех пор, пока у них не появляется мальчик, а затем останавливается. Каково соотношение мальчиков и девочек в этой стране?</p><p>Игнорируйте ситуации, когда рождаются двойняшки, тройняшки и так далее, пары, не имеющие детей, и пары, умершие до того, как у них появится мальчик.</p><p>Как обычно, предлагаем порассуждать над решением в комментариях. Проверить свой ответ можно на сайте по прикреплённой ссылке, там мы даём наш вариант решения.</p><p>Ответ</p><p>Задачи на прикидку, то есть подразумевающие приближенное решение — популярный класс задач, которые предлагают на собеседованиях в IT компании. Предлагаем вам несколько таких задач, а также <a href="https://tproger.ru/problems/fermi/">рассказ</a> об общих методах их решения и <a href="https://tproger.ru/problems/fermi/#cheats">конкретные советы</a> для собеседований.</p><p>Сколько флаконов шампуня производится в мире за год? Ответ</p><p>Сколько насечек на ребре четвертака — монеты в 25 центов? Ответ</p><p>Сколько будет 2 в 64 степени? Ответ</p><p>Сколько туалетной бумаги потребуется, чтобы покрыть ею весь штат? Ответ</p><p>Сколько атомов резины стираются с шины автомобильного колеса при каждом его обороте? Ответ</p><p>Cколько денег понадобится на мытье всех окон в Сиэтле? Ответ</p><p>Также смотрите <a href="https://tproger.ru/problems/fermi/#problems">примеры других задач</a> для самостоятельного решения.</p><p>Задача, которую давали на собеседованиях в Apple. От вас требуется написать функцию, которая возвращает максимальную прибыль от одной сделки с одной акцией (сначала покупка, потом продажа). Исходные данные — массив вчерашних котировок stock_prices_yesterday с ценами акций Apple.<br />Информация о массиве:</p><ul><li>Индекс равен количеству минут с начала торговой сессии (9:30 утра).</li><li>Значение в массиве равно стоимости акции в это время.</li></ul><p>Например: если акция в 10:00 утра стоила 20 долларов, то<br />stock_prices_yesterday[30] = 20.</p><p>Допустим, имеем некоторые условия:</p><p>Массив может быть любым, хоть за весь день. Нужно написать функцию get_max_profit как можно эффективнее — с наименьшими затратами времени выполнения и памяти.</p><p>Ответ</p><p>Задача про слияние промежутков в календаре.</p><p>Предположим, компания, в которой вы работаете, разрабатывает электронный календарь. В календаре есть функция, показывающая, когда различные команды программистов будут заняты на какой-либо встрече.</p><p>Те периоды, когда команда занята, на календаре отмечены как диапазоны времени, например, с 10:00 до 12:30 или с 12:30 до 13:00. В разрабатываемой программе промежуток времени представлен в виде <a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D1%80%D1%82%D0%B5%D0%B6_(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)">кортежей</a> из двух целых чисел. Число означает номер 30-минутного блока, который идет после 9:00 утра. Например, кортеж (2, 4) означает диапазон с 10:00 до 11:00, а (0, 1) — это промежуток 9:00-9:30.</p><p>Вам нужно написать функцию, которая должна упростить вывод информации таким образом, что если команда занята в промежутках с 10:00 до 12:30 и с 12:30 до 13:00, то это отображалось как 10:00‒13:00. Например: на входе вашей функции неупорядоченный массив из кортежей [(0, 1), (3, 5), (4, 8), (10, 12), (9, 10)], а на выходе вы должны получить упорядоченный массив [(0, 1), (3, 8), (9, 12)].</p><p>В будущем планируется внести изменения в программу, где вместо 30-минутных блоков будут минутные, как это реализовано в представлении <a href="https://ru.wikipedia.org/wiki/UNIX-%D0%B2%D1%80%D0%B5%D0%BC%D1%8F">Unix-времени</a>. С учетом этого изменения нужно, чтобы ваша функция уже сейчас могла работать с большими числами. Еще не забудьте, что кортеж — это такой тип данных, в котором содержимое переменной невозможно изменять после ее создания.</p><p>Ответ</p><p>Задача, которую давали на собеседованиях в Apple. Представьте, что вы получили работу кассира в магазине. Ваш босс случайно выяснил, что вы обладаете навыками программиста, и захотел, чтобы вы помогли ему написать программу.</p><p>Входные данные:</p><ol><li>Указанная сумма денег.</li><li>Массив со всеми доступными номиналами монет.</li></ol><p>Нужно написать функцию, которая на выходе выдаст количество всех возможных способов получить указанную сумму денег при помощи различных доступных номиналов монет. Например, если вам нужно получить 4 цента из монет номиналами 1, 2 и 3 цента, то функция вернет 4 — именно столько есть возможных комбинаций из чисел 1, 2 и 3, чтобы получить в сумме 4:</p><ol><li>1, 1, 1, 1.</li><li>1, 1, 2.</li><li>1, 3.</li><li>2, 2.</li></ol><p>Ответ</p><p>Эту задачу когда-то давали в Google.</p><p>Вам нужно подняться по лестнице. За один раз можно подняться на одну или две ступеньки. Сколько существует способов добраться до N-й ступеньки?</p><p>Ответ</p><p>Эту задачу <a href="https://web.archive.org/web/20160402060709/https://medium.com/@bearsandsharks/i-failed-a-twitter-interview-52062fbb534b">задавали</a> на собеседовании в Twitter.<br />Рассмотрим следующую картинку:</p><figure><img src="https://media.tproger.ru/uploads/2016/05/1-9BE6dgt1cTDOHZSON7mlzQ.jpeg" alt="" /></figure><p>На этой картинке изображены стены различной высоты в некотором плоском мире. Картинка представлена массивом целых чисел, где индекс — это точка на оси X, а значение каждого индекса — это высота стены (значение по оси Y). Картинке выше соответствует массив [2, 5, 1, 2, 3, 4, 7, 7, 6].</p><p>Теперь представьте, что начался дождь, который не прекращается и поливает стены сверху равномерным потоком. Сколько воды соберется в «лужах» между стенами?</p><figure><img src="https://media.tproger.ru/uploads/2016/05/1-MKQZbWOdLPK-DD10Y48fkQ.jpeg" alt="" /></figure><p>задача про стены и дождь, собеседование в Twitter</p><p>Единицей объема воды считаем квадратный блок 1×1. На картинке выше всё, что расположено слева от точки 1, выплескивается. Вода справа от точки 7 также прольется. У нас остается лужа между 1 и 6 — таким образом, получившийся объем воды равен 10.</p><p>Ответ</p><h2>Задачи на нестандартное мышление</h2><p>Задача про бесконечный поезд.</p><p>Представьте себе замкнутую по окружности железную дорогу. По ней едет поезд, последний вагон которого скреплён с первым так, что внутри можно свободно перемещаться между вагонами. Вы оказались в одном случайном вагоне и ваша задача — подсчитать их общее количество. В каждом вагоне можно включать или выключать свет, но начальное положение переключателей случайное и заранее неизвестно.</p><p>Все вагоны внутри выглядят строго одинаково, окна закрыты так, что невозможно посмотреть наружу, движение поезда равномерное. Помечать вагоны как-либо, кроме включения или выключения света, нельзя. Количество вагонов конечно (не верьте названию задачи).</p><p>Ответ</p><p>Вы стоите перед закрытой комнатой, в которой есть три лампочки. На стене перед вами три переключателя: каждый из которых включает или выключает одну из лампочек. Вам нужно узнать, какой переключатель к какой лампочке относится, при условии, что зайти в комнату вы можете только один раз.</p><p>Расположение переключателей случайное, порядок подключения заранее неизвестен. Зайдя в комнату, можно делать с лампочками всё, что угодно, но уже нельзя вернуться к переключателям. Изначально все лампы выключены.</p><p>Если вы хотите решить задачу самостоятельно, но в голову ничего не приходит, можете воспользоваться нашей подсказкой.</p><p>Или смотрите сразу ответ</p><p>Классическая задача. Найдите в данной вам строке максимальную по длине подстроку, которая является палиндромом (то есть читается слева направо и справа налево одинаково). Предложите как можно более эффективный алгоритм.</p><p>Ответ</p><p>Реализуйте функцию извлечения квадратного корня, не пользуясь встроенными в язык средствами нахождения корня и возведения в степень.</p><p>Ответ</p><p>В этой задаче вам необходимо реализовать функцию, которая бы проверяла число на четность, используя только битовые операции AND, OR, NOT.</p><p>Ответ</p><p>На прямой даны N отрезков (в реальной жизни это могут быть промежутки времени, например), которые заданы координатами их левого и правого конца. Для каждого данного отрезка необходимо узнать, сколько из данных отрезков полностью находятся в нем. Один отрезок полностью содержится во втором, если левый конец первого отрезка находится правее левого конца второго отрезка, а правый конец первого находится левее правого конца второго. Предложите как можно более эффективный способ решения этой задачи. Гарантируется, что все концы данных отрезков различны.</p><p>Если вы придумали решение, то написать и проверить его вы можете <a href="http://codeforces.com/contest/652/problem/D">здесь</a>, на codeforces.</p><p>Сможете ли вы решить эффективно данную задачу в случае, если концы отрезков могут совпадать?</p><p>Ответ</p><p>Придумать алгоритм, определяющий, все ли символы в строке встречаются один раз.<br />При выполнении этого задания нельзя использовать дополнительные структуры данных.<br />Ответ</p><p>В массиве случайных чисел A[0…n-1] задан один «волшебный» индекс: такой, что A[i] = i. Значения элементов в массиве повторяться не могут. Учитывая, что массив отсортирован по значениям в порядке возрастания, напишите метод, который определит этот «волшебный» индекс, если он существует в массиве A. Если элемента в массиве нет, верните любое отрицательное число.</p><p>Как изменится решение, если известно, что таких индексов в массиве несколько?</p><p>Ответ</p><p>Как можно узнать количество дней в месяце, зная его номер? Другими словами, опишите, как получить функцию f(x), которая бы давала следующий список значений:</p><p><a href="https://media.tproger.ru/uploads/2016/10/table1.png"></a></p><p>В качестве аргумента мы получаем только номер месяца, т.е. мы не учитываем високосные года, и f(2) = 28.</p><p>Ответ</p><p>Задачка для питонистов: нужно перебрать все пары символов в строке, и остановиться при нахождении двух одинаковых символов.</p><p>Решение достаточно очевидное, но возникает вопрос:</p><p>Если бы мы программировали, например, на Java, то мы могли бы воспользоваться механизмом меток:</p><p>Однако в Python такого механизма нет. Требуется предложить наиболее удобное в использовании и читаемое решение.</p><p>Ответ</p><p>Написать код, который проверяет, пересекутся ли две заданные прямые, лежащие в одной плоскости.<br />Предположим, что нам необходимо разработать структуру данных для хранения информации о прямой, и будем считать, что если две линии совпадают, то они пересекаются.</p><p>Ответ</p><p>Классическая задача: посчитать N-е число последовательности, в которой каждый элемент равен сумме двух предыдущих. Такая последовательность называется последовательностью Фибоначчи: 1, 1, 2, 3, 5, 8…</p><p>Очень часто на разнообразных олимпиадах попадаются задачи вроде этой, которые, как думается на первый взгляд, можно решить с помощью простого перебора. Но если мы подсчитаем количество возможных вариантов, то сразу убедимся в неэффективности такого подхода: например, простая рекурсивная функция, приведенная ниже, будет потреблять существенные ресурсы уже на 30-ом числе Фибоначчи, тогда как на олимпиадах время решения часто ограничено 1-5 секундами.</p><p>Придумайте, как найти N’е число Фибоначчи за приемлемое время.</p><p>Ответ</p><p>Чтобы разобраться в теме, рекомендуем почитать нашу <a href="https://tproger.ru/articles/dinprog-starters/">статью про динамическое программирование</a> для начинающих.</p><h2>Задачи на программирование</h2><p>Одна из самых известных задач Интернета, будоражащая многие светлые умы человечества.</p><p>Самолет стоит на взлетной полосе с подвижным покрытием типа транспортера. Покрытие может двигаться против направления взлета самолета, то есть ему навстречу. Транспортер автоматически регулирует свою скорость таким образом, чтобы самолет оставался неподвижным. Вопрос: сможет ли самолет в таких условиях взлететь?</p><p><a href="https://media.tproger.ru/uploads/2016/11/x_06ad251d.jpg"></a></p><p>Ответ</p><p>Задача на перегрузку функций в C++, которая может оказаться сложнее, чем выглядит.</p><p>Предположим, у нас есть два класса:</p><p>Что выведут два следующих куска кода и почему?</p><p>Ответ</p><p>Рассмотрим ситуацию, когда три работника хотят вычислить свою среднюю зарплату при условии, что каждый знает свою зарплату, но не может сообщить ее другому напрямую. Обмен информации между людьми возможен, но передаваемые друг другу сообщения не должны содержать какую-либо конкретную информацию об уровне зарплат. Как это сделать?</p><p>Ответ</p><p>Пусть у нас есть массив положительных чисел, в котором все числа, кроме трех, встречаются по 2 раза, а эти три числа отличны от всех остальных и встречается каждое ровно по одному разу. Нужно найти эти три числа. Числа помещаются в 32-битный целочисленный тип.</p><p>Ответ</p><p>Положим, у нас есть некоторая конечная последовательность чисел и мы имеем итератор, указывающий на первый элемент. Мы можем при помощи итератора посмотреть значение текущего элемента и перейти к следующему элементу. Требуется построить такой алгоритм выбора случайного элемента из этой последовательности, чтобы каждый элемент мог оказаться выбранным с равной вероятностью.</p><p>Ограничения: мы можем использовать O(1) дополнительной памяти и не можем создавать новый итератор. Можно пользоваться функцией генерации случайного числа от [0;1).</p><p>Ответ</p><p>Известная задача с IT-собеседований с несколькими вариантами решения: как правильно реализовать обмен значений переменных?</p><p>Ответ</p><p>На одной стороне реки находятся три человека и три льва. Все они должны оказаться на другом берегу реки. Есть лишь одна лодка, в которой могут поместиться лишь два живых существа одновременно (человека или льва). Вы не можете оставлять на том или другом берегу реки больше львов, чем людей, так как в этом случае животные съедят людей, оставшихся в меньшинстве. Как вы переправите всех через реку?</p><p>Ответ</p><p>Если бы вы получили стопку монет достоинством в один пенс каждая и высотой с Эмпайр-стейт-билдинг, поместились бы все эти деньги в одном помещении?</p><p>Сперва может показаться, что это одна из тех головоломок, в которых предполагается оценить какое-то абсурдное число. Но на самом деле это не так, подумайте хорошенько.</p><p>Ответ</p><h2>Часто задаваемые вопросы</h2><h3>Какие задачи дают на IT-собеседованиях?</h3><p>Чаще всего дают алгоритмические задачи, задачи на структуры данных и логические головоломки.</p><h3>Как подготовиться к интервью?</h3><p>Повторите алгоритмы, решайте задачи на LeetCode, практикуйтесь объяснять решение вслух.</p><h3>На каком языке решать задачи?</h3><p>Python популярен благодаря краткому синтаксису. Java и C++ тоже часто используются.</p><p>Также рекомендуем по теме:</p><ul><li><a href="https://tproger.ru/digest/competitive-programming-practice/">28 cайтов с задачами по программированию</a></li><li><a href="https://tproger.ru/translations/top-ten-interview-preparation-mistakes/">Десять наиболее частых ошибок программистов при подготовке к собеседованию</a></li><li><a href="https://tproger.ru/problems/string-algorithms/">Подборка полезных алгоритмов для собеседований: задачи на строки</a></li><li><a href="https://tproger.ru/problems/technocup-problems-2017/">14 алгоритмических задач с разбором решений по итогам «Технокубка» 2017</a></li><li><a href="https://tproger.ru/problems/technocup-final-solutions/">Олимпиада «Технокубок»: разбор задач финального раунда</a></li><li><a href="https://tproger.ru/problems/russian-code-cup-2017/">Разбираем решения задач предварительного тура Russian Code Cup</a></li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Представьте, что существует квадратная матрица, каждый пиксел которой может быть черным или белым. Разработайте алгоритм поиска максимального субквадрата, у которого все стороны черные</title>
      <link>https://tproger.ru/problems/max-black-bordered-submatrix</link>
      <comments>https://tproger.ru/problems/max-black-bordered-submatrix?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/max-black-bordered-submatrix</guid>
      <description><![CDATA[<p>Каждый пиксел квадратной матрицы чёрный или белый: простое решение перебором за O(N⁴) и более сложный, но быстрый вариант алгоритма.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/max-black-bordered-submatrix">Представьте, что существует квадратная матрица, каждый пиксел которой может быть черным или белым. Разработайте алгоритм поиска максимального субквадрата, у которого все стороны черные</a>»</p>]]></description>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 22 Jul 2015 14:33:20 GMT</pubDate>
      <content:encoded><![CDATA[<p>Эту задачу также можно решить двумя способами: простым и сложным. Давайте рассмотрим оба решения.</p><h3>«Простое» решение: O(N4)</h3><p>Мы знаем, что длина стороны самого большого квадрата равна N и существует только один квадрат размером N*N. Можно проверить, является ли квадрат искомым, и сообщить, если это так.</p><p>Если квадрат размером N*N не найден, можно попытаться найти следующий квадрат: (N-1)*(N-1). Проверяя все квадраты этого размера, мы возвращаем первый найденный квадрат. Затем аналогичные операции повторяются для N-2, N-3 и т. д. Так как каждый раз мы уменьшаем размер квадрата, то первый найденный квадрат будет самым большим.</p><p>Наш код работает так:</p><h3>Решение с предварительной обработкой: O(N3)</h3><p>Неторопливость «простого» решения связана с тем, что мы должны произвести O(N) операций при каждой проверке квадрата–кандидата. Проведя предварительную обработку, можно сократить время isSquare до O(1), тогда алгоритм потребует O(N3) времени.</p><p>isSquare пытается узнать, не являются ли нулевыми squareSize, находящиеся правее (и ниже) определенных ячеек. А эту информацию можно узнать заранее.</p><p>Мы выполним проверку справа налево и снизу вверх. Для каждой ячейки нужно рассчитать:</p><p>Посмотрите на значения для некоторой матрицы.</p><p>Далее приведен код этого алгоритма. Обратите внимание, что findSquare и findSquare — WithSize совпадают, за исключением вызова processMatrix и последующей работы с новым типом данных:</p><p>Разбор задачи по книге «Карьера программиста. Как устроиться на работу в Google, Microsoft или другую ведущую IT-компанию»</p>]]></content:encoded>
    </item>
    <item>
      <title>Вас уменьшили до размеров 5-центовой монеты и бросили в блендер</title>
      <link>https://tproger.ru/problems/you-are-shrunk-to-the-height-of-a-nickel-and-thrown-into-a-blender</link>
      <comments>https://tproger.ru/problems/you-are-shrunk-to-the-height-of-a-nickel-and-thrown-into-a-blender?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Алексей Михайлишин]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/you-are-shrunk-to-the-height-of-a-nickel-and-thrown-into-a-blender</guid>
      <description><![CDATA[<p>Разбор знаменитой задачи Google про блендер и 5-центовую монету. 7 популярных ответов и лучшее решение, основанное на законах физики масштабирования.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/you-are-shrunk-to-the-height-of-a-nickel-and-thrown-into-a-blender">Вас уменьшили до размеров 5-центовой монеты и бросили в блендер</a>»</p>]]></description>
      <category><![CDATA[Головоломки]]></category>
      <category><![CDATA[Задачи повышенной сложности]]></category>
      <category><![CDATA[Google]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 15 Dec 2014 16:10:37 GMT</pubDate>
      <content:encoded><![CDATA[<p>• Лучший ответ на задачу Google про блендер — просто выпрыгнуть из него, используя законы физики масштабирования
• Ключевая подсказка в условии — слово «плотность»: при уменьшении размера сила мускулов относительно веса возрастает
• Высота прыжка не зависит от размера тела (закон Борелли), поэтому уменьшенный человек легко перепрыгнет стенку блендера
• Задача проверяет умение мыслить нестандартно и применять базовые законы физики к необычным ситуациям</p><blockquote>Вас уменьшили до размеров 5-центовой монеты и бросили в блендер. Ваш вес уменьшился так, что плотность вашего тела осталась прежней. Лезвия начнут вращаться через 60 секунд. Ваши действия?</blockquote><p>Это классическая google-задачка, хороший разбор которой в рунете не так просто найти. Мы подготовили его для вас, но предлагаем сначала самим порассуждать над решением. Абсолютного правильного ответа нет, но есть те, которые явно лучше остальных.</p><p>Начнём с классификации наиболее популярных ответов, затем расскажем про тот, который считается лучшим среди интервьюверов в Google.</p><p>Многие соискатели выдают один забавный ответ: «Так как блендер очень скоро включат, можно предположить, что в него положат какие-то продукты, и поэтому мне, может быть, лучше подставить свою шею под лезвие, чем задохнуться из-за паров той жижи, которая скоро появится в блендере». Если же говорить о часто встречающихся серьезных ответах, то лидерами являются такие.</p><p><b>Первый</b>. Лечь как можно плотнее к днищу, чтобы лезвия крутились надо мной.</p><p><b>Второй</b>. Встать с той стороны блендера, где крепятся лезвия. Возможно, между стенкой и устройством крепления есть зазор шириной в 5-центовую монету.</p><p><b>Третий</b>. Залезть по лезвию на ось вращения и найти такое место, где при вращении лезвий можно сохранять равновесие. Схватиться покрепче. Итоговая центростремительная сила в этом случае будет близка к нулю, что и позволит удержаться.</p><p>Первые три варианта дают некоторый шанс на выживание, но что если лезвия будут крутиться долго? Или конструкция такова, что вас всё таки заденет остриём? И вообще, если вдуматься, кто и зачем вас бросил в блендер? Если это какие-то враждебные существа, которые собираются приготовить соус из человека, то ваши долгосрочные шансы на выживание будут очень небольшими при любом варианте.</p><p>Вот стандартные ответы интервьюверов на уточняющие вопросы: «По поводу враждебных существ не беспокойтесь». «Никакой жидкости добавлено не будет». «Крышки у бледнера нет». «Исходите из того, что лезвия будут вращаться до тех пор, пока вы не погибните».</p><p>Четвертый подход отличается — нужно выбраться во вне. Интервьювер поинтересуется, как вы будете это делать. Одним из самых ярких ответов был такой: при очень малом весе вы сможете взобраться по стенке примерно так же, как это делают мухи.</p><p><b>Пятый</b>, не самый оптимистичный, вариант — воспользоваться телефоном и позвонить или отправить sms с просьбой о помощи. Тут всё зависит от того, уменьшился ли так же ваш телефон, сможет ли он работать с базовой станцией (которая осталась прежней) и какова будет скорость реакции службы спасения (и будет ли вообще?).</p><p><b>Шестой</b> вариант: разорвать одежду на полосы, чтобы сделать из них верёрвку и воспользоваться её, чтобы выбраться. Но реально ли это сделать за одну минуту? Как крепить верёвку сверху? И даже если это удастся, как потом спуститься вниз?</p><p>Есть и <b>седьмой</b>: использовать одежду и собственные усилия, чтобы как-то заблокировать (или даже сломать) лезвия или работу мотора. Но и здесь могут возникнуть проблемы.</p><p>Ни один из перечисленных ответов не принесёт вам в Google много баллов. Интервьюверы рассказывали, что лучший ответ, который они слышали был таким — выпрыгнять из блендера.</p><p>Ух ты? В вопросе даётся важный ключ — слово «плотность». Эта подсказка наводит на мысль, что важны вес и объем тела (а на другие «нереалистичности» можно не обращать внимания) и что подходящий ответ должен строиться на простейших законах физики.</p><p>Короче: интервьювер хочет, чтобы вы сфокусировались на последствиях, связанных с изменением размера. Вы, вероятно, слышали, что муравей способен поднять вес, в 50 раз превышающий вес его тела. Это объясняется не тем, что его мускулы лучше, чем у человека, а тем, что муравей маленький. Вес любого живого существа пропорционален кубу его высоты. Сила мускулов и скелета, поддерживающего их, зависит от площади их поперечного сечения, которая пропорциональна квадрату высоты. Если вас уменьшить до 1/10 вашего роста, сила ваших мускулов уменьшится в сто раз, но ваш вес уменьшится еще больше — в тысячу раз. Про прочих равных условиях небольшие существа «сильнее».</p><figure><img src="https://media.tproger.ru/uploads/2014/12/Vl2Ceq10VSo.jpg" alt="" /></figure><p>В середине 1600-х годов Джованни Альфонсо Борелли, современник Галилео, предположил, что всё, что прыгает, поднимается примерно на одинаковую высоту. Подумайте хорошенько об этом. Если вы физически здоровы, то, вероятно, сможете подпрыгнуть сантиметров на 70. Эта высота не преграда и для других живых существ: лошади, кролика, лягушки, кузнечика или блохи. Разумеется, есть вариации, но общее правило именно такое: самые крутые баскетболисты NBA могут поднять свой центр тяжести примерно на такую же высоту, как и блоха.</p><p>Мускульная энергия в конечном счёте определяется химическими процессами: глюкозой и водородом, циркулирующем в крови, а также АТФ, имеющимся в клетках мускул. Количество любых хим. веществ пропорционально объему вашего тела т.е. если вы уменьшитесь до 1/n вашего размера, то мускульная энергия сократится в n³ раз.</p><p>К счастью, вес уменьшится так же. Поэтому при размере в монетку, высота вашего прыжка (если не учитывать сопротивление воздуха) никак не изменится. Высота блендера примерно 30 см. Если вы можете сейчас перепрыгнуть через препятствие такой высоты, то удрать из блендера для вас не будет проблемой.</p><p>Возможно, вы спросите, как же упав потом с такой высоты вы не поломаете себе кости? Поверхность, которую вы теперь занимаете, составит 1/n² по сравнению с вами обычным, а вес сократится еще больше, до 1/n³ прежнего. Соотношение площади поверхности к весу возрастёт в n раз, поэтому когда вы приземлитесь, никаких повреждений у вас не будет. Это объясняет, почему любое существо размером с мышь и менее может не беспокоиться и падать с любой высоты.<br />Разбор взят из книжки «<a href="http://en.wikipedia.org/wiki/Are_You_Smart_Enough_to_Work_at_Google%3F">Are You Smart Enough to Work at Google?</a>».</p><h2>Часто задаваемые вопросы</h2><h3>Зачем в Google задавали задачу про блендер?</h3><p>Задача про блендер — пример brainteaser-вопроса, который Google использовал на собеседованиях до 2013 года. Она проверяла не знание физики, а способность кандидата мыслить структурно, находить ключевые подсказки в условии и строить логичные рассуждения в условиях неопределённости. Позже Google отказался от подобных вопросов, признав их слабым предиктором успешности на работе.</p><h3>Почему уменьшенный человек может выпрыгнуть из блендера?</h3><p>При уменьшении тела его вес снижается пропорционально кубу размера, а мускульная энергия — тоже пропорционально кубу. В результате высота прыжка остаётся прежней (закон Борелли). Человек ростом с монетку сохраняет способность подпрыгнуть на 50–70 см, а высота блендера — около 30 см. Этого достаточно, чтобы выбраться.</p><h3>Какие ещё brainteaser-задачи задавали в Google?</h3><p>Среди известных задач Google: «Сколько мячей для гольфа поместится в школьный автобус?», «Почему канализационные люки круглые?» и «Сколько настройщиков пианино в Чикаго?» (задача Ферми). Все они проверяли умение декомпозировать проблему и делать обоснованные оценки. Подробный разбор подобных задач можно найти в книге «Are You Smart Enough to Work at Google?».</p>]]></content:encoded>
    </item>
  </channel>
</rss>