PHP | LeetCode
الذهاب إلى القناة على Telegram
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv
إظهار المزيد1 356
المشتركون
-124 ساعات
-67 أيام
-930 أيام
أرشيف المشاركات
1 356
Задача: 1022. Sum of Root To Leaf Binary Numbers
Сложность: easy
Вам дан корень двоичного дерева, в котором каждый узел имеет значение 0 или 1. Каждый путь от корня к листьям представляет собой двоичное число, начиная со старшего бита. Например, если путь 0 -> 1 -> 1 -> 0 -> 1, то в двоичном виде это может представлять 01101, что равно 13. Для всех листьев дерева рассмотрите числа, представленные путем от корня к этому листу. Верните сумму этих чисел. Тестовые примеры генерируются таким образом, чтобы ответ помещался в 32-битовое целое число.
Пример:
Input: root = [1,0,1,0,1,0,1] Output: 22👨💻 Алгоритм: 1⃣Рекурсивный обход дерева: Используйте функцию DFS (поиск в глубину) для обхода дерева, начиная от корня. Передавайте текущее значение числа по пути как параметр. 2⃣Анализ текущего узла: Если узел является листом (не имеет потомков), добавьте текущее значение числа к общей сумме. Если узел не является листом, рекурсивно вызовите функцию DFS для левого и правого дочерних узлов, обновляя текущее значение числа. 3⃣Возврат результата: После завершения обхода верните общую сумму чисел, представленных путями от корня к листьям. 😎 Решение:
class TreeNode {
public $val = 0;
public $left = null;
public $right = null;
function __construct($val = 0, $left = null, $right = null) {
$this->val = $val;
$this->left = $left;
$this->right = $right;
}
}
class Solution {
function sumRootToLeaf($root) {
return $this->dfs($root, 0);
}
private function dfs($node, $currentValue) {
if ($node === null) return 0;
$currentValue = ($currentValue << 1) | $node->val;
if ($node->left === null && $node->right === null) return $currentValue;
return $this->dfs($node->left, $currentValue) + $this->dfs($node->right, $currentValue);
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 1485. Clone Binary Tree With Random Pointer
Сложность: medium
Дано бинарное дерево, такое что каждый узел содержит дополнительный случайный указатель, который может указывать на любой узел в дереве или быть null.
Верните глубокую копию дерева.
Дерево представлено в том же формате ввода/вывода, что и обычные бинарные деревья, где каждый узел представлен в виде пары [val, random_index], где:
- val: целое число, представляющее Node.val
- random_index: индекс узла (во входных данных), на который указывает случайный указатель, или null, если он не указывает ни на один узел.
Вам будет дано дерево в классе Node, и вы должны вернуть клонированное дерево в классе NodeCopy. Класс NodeCopy является клоном класса Node с такими же атрибутами и конструкторами.
Пример:
Input: root = [[1,null],null,[4,3],[7,0]]
Output: [[1,null],null,[4,3],[7,0]]
Explanation: The original binary tree is [1,null,4,7].
The random pointer of node one is null, so it is represented as [1, null].
The random pointer of node 4 is node 7, so it is represented as [4, 3] where 3 is the index of node 7 in the array representing the tree.
The random pointer of node 7 is node 1, so it is represented as [7, 0] where 0 is the index of node 1 in the array representing the tree.
👨💻 Алгоритм:
1⃣Глубокое копирование дерева:
Инициализируйте хэш-таблицу newOldPairs, которая сопоставляет узлы старого дерева с узлами нового дерева.
Создайте функцию deepCopy(root), которая принимает корень данного дерева и возвращает корень нового дерева. Эта функция создаёт новый узел с теми же значениями, что и корневой узел, и рекурсивно копирует левое и правое поддеревья. Затем она сохраняет пару старого и нового узлов в хэш-таблицу и возвращает новый корень.
2⃣Сопоставление случайных указателей:
Создайте функцию mapRandomPointers(oldNode), которая принимает корень старого дерева и рекурсивно сопоставляет случайные указатели нового дерева с соответствующими узлами старого дерева, используя хэш-таблицу newOldPairs.
3⃣Возвращение клонированного дерева:
Создайте глубокую копию дерева, используя функцию deepCopy(root), и сопоставьте все случайные указатели нового дерева с помощью функции mapRandomPointers(root). Верните новый корень.
😎 Решение:
class Node {
public $val;
public $left;
public $right;
public $random;
function __construct($val = 0, $left = null, $right = null, $random = null) {
$this->val = $val;
$this->left = $left;
$this->right = $right;
$this->random = $random;
}
}
class NodeCopy {
public $val;
public $left;
public $right;
public $random;
function __construct($val = 0, $left = null, $right = null, $random = null) {
$this->val = $val;
$this->left = $left;
$this->right = $right;
$this->random = $random;
}
}
class Solution {
private $newOldPairs = [];
private function deepCopy($root) {
if ($root === null) {
return null;
}
$newRoot = new NodeCopy($root->val);
$newRoot->left = $this->deepCopy($root->left);
$newRoot->right = $this->deepCopy($root->right);
$this->newOldPairs[spl_object_id($root)] = $newRoot;
return $newRoot;
}
private function mapRandomPointers($oldNode) {
if ($oldNode === null) {
return;
}
$newNode = $this->newOldPairs[spl_object_id($oldNode)];
if ($newNode) {
$newNode->random = $this->newOldPairs[spl_object_id($oldNode->random)] ?? null;
$this->mapRandomPointers($oldNode->left);
$this->mapRandomPointers($oldNode->right);
}
}
public function copyRandomBinaryTree($root) {
$newRoot = $this->deepCopy($root);
$this->mapRandomPointers($root);
return $newRoot;
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 647. Palindromic Substrings
Сложность: medium
Если задана строка s, верните количество палиндромных подстрок в ней. Строка является палиндромом, если она читается так же, как задом наперед. Подстрока - это непрерывная последовательность символов в строке.
Пример:
Input: s = "abc" Output: 3👨💻 Алгоритм: 1⃣Инициализируйте счетчик для подсчета палиндромных подстрок. 2⃣Для каждой позиции в строке используйте два метода расширения: один для палиндромов нечетной длины и один для палиндромов четной длины. 3⃣Расширяйте от центра, проверяя, является ли подстрока палиндромом, и увеличивайте счетчик, если условие выполняется. 😎 Решение:
function countSubstrings($s) {
$totalCount = 0;
function expandAroundCenter($s, $left, $right) {
$count = 0;
while ($left >= 0 && $right < strlen($s) && $s[$left] == $s[$right]) {
$count++;
$left--;
$right++;
}
return $count;
}
for ($i = 0; $i < strlen($s); $i++) {
$totalCount += expandAroundCenter($s, $i, $i);
$totalCount += expandAroundCenter($s, $i, $i + 1);
}
return $totalCount;
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача №19. Remove Nth Node From End of List
Сложность: medium
Учитывая заголовок связанного списка, удалите n-й узел из конца списка и верните его заголовок.
Пример:
Input: head = [1,2,3,4,5], n = 2 Output: [1,2,3,5]👨💻 Алгоритм: 1⃣Определить длину списка, пройдясь по нему один раз. 2⃣Найти узел, предшествующий удаляемому, используя второй проход. 3⃣Изменить ссылки, чтобы удалить целевой узел. 😎 Решение:
class Solution {
function removeNthFromEnd($head, $n) {
$tamaño = 0;
$aux = $head;
while ($aux !== null) {
$aux = $aux->next;
$tamaño++;
}
if ($tamaño == 1) {
return null;
}
if ($tamaño == $n) {
return $head->next;
}
$aux = $head;
for ($i = 0; $i < $tamaño - $n - 1; $i++) {
$aux = $aux->next;
}
$aux->next = $aux->next->next;
return $head;
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
АЙТИШНИКИ, ХВАТИТ сливать время на прилизанные новости и бесполезные курсы
Проект «ИИнтеллигенция» стал главным каналом для тех, кто использует нейросети на уровне разработки, автоматизации и опенсорса, а не просто балуется в чатах. Здесь собирают только то, что реально экономит человеко-часы и работает в проде.
🎓 Готовые ИИ-сервисы, промпты и ИИ-агенты для автоматизации рутины
📚 Разборы полезных ИИ-инструментов, локальных LLM и опенсорс-репозиториев
🛠 Практические кейсы, гайды по деплою моделей и интеграции ИИ в пайплайны
⚡️ Технические ИТ-новости без маркетинговой воды и душных отчетов
Обучение и прокачка в реальном времени: работа с API (Claude, GPT), локалки (Ollama, vLLM), автоматизация кода, опенсорс-утилиты, AI-агенты и др.
Ценишь время и работаешь с ИИ, подпишись: @clucai
1 356
Задача: 892. Surface Area of 3D Shapes
Сложность: easy
Вам дана сетка n x n, на которой вы разместили несколько кубиков 1 x 1 x 1. Каждое значение v = grid[i][j] представляет собой башню из v кубиков, размещенных на вершине ячейки (i, j). После размещения кубиков вы решили склеить все непосредственно прилегающие кубики друг с другом, образовав несколько неправильных 3D-фигур. Верните общую площадь поверхности получившихся фигур. Примечание: нижняя грань каждой фигуры учитывается в площади ее поверхности.
Пример:
Input: grid = [[1,2],[3,4]] Output: 34👨💻 Алгоритм: 1⃣Пройти по всей сетке и для каждой башни (ячейки) посчитать начальную площадь поверхности: добавить площадь верхней и нижней граней, а также четыре боковые грани. 2⃣Для каждой башни уменьшить площадь боковых граней, которые прилегают к соседним башням, с учетом высоты соседних башен. 3⃣Просуммировать все значения площадей для получения итоговой площади поверхности. 😎 Решение:
function surfaceArea($grid) {
$n = count($grid);
$area = 0;
for ($i = 0; $i < $n; $i++) {
for ($j = 0; $j < $n; $j++) {
if ($grid[$i][$j] > 0) {
$area += ($grid[$i][$j] * 4) + 2;
}
if ($i > 0) {
$area -= min($grid[$i][$j], $grid[$i-1][$j]) * 2;
}
if ($j > 0) {
$area -= min($grid[$i][$j], $grid[$i][$j-1]) * 2;
}
}
}
return $area;
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 1062. Longest Repeating Substring
Сложность: medium
Дана строка s. Вернуть длину самой длинной повторяющейся подстроки. Если повторяющаяся подстрока отсутствует, вернуть 0.
Пример:
Input: s = "abcd"
Output: 0
Explanation: There is no repeating substring.
👨💻 Алгоритм:
1⃣Перемещайте скользящее окно длиной L по строке длиной N.
2⃣Проверьте, находится ли строка в скользящем окне в хэш-наборе уже виденных строк. Если да, то повторяющаяся подстрока находится здесь. Если нет, сохраните строку из скользящего окна в хэш-наборе.
3⃣Очевидный недостаток этого подхода — большое потребление памяти в случае длинных строк.
😎 Решение:
class Solution {
function search($L, $n, $S) {
$seen = [];
for ($start = 0; $start <= $n - $L; ++$start) {
$tmp = substr($S, $start, $L);
if (in_array($tmp, $seen)) return $start;
$seen[] = $tmp;
}
return -1;
}
function longestRepeatingSubstring($S) {
$n = strlen($S);
$left = 1; $right = $n;
while ($left <= $right) {
$L = $left + intdiv($right - $left, 2);
if ($this->search($L, $n, $S) !== -1) {
$left = $L + 1;
} else {
$right = $L - 1;
}
}
return $left - 1;
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 830. Positions of Large Groups
Сложность: easy
В строке s из строчных букв эти буквы образуют последовательные группы одного и того же символа.
Например, строка s = "abbxxxxzyy" имеет группы "a", "bb", "xxxx", "z" и "yy".
Группа идентифицируется интервалом [start, end], где start и end обозначают начальный и конечный индексы (включительно) группы. В приведенном выше примере "xxxx" имеет интервал [3,6].
Группа считается большой, если в ней 3 или более символов.
Верните интервалы каждой большой группы, отсортированные в порядке возрастания начального индекса.
Пример:
Input: s = "abcdddeeeeaabbbcd" Output: [[3,5],[6,9],[12,14]] Explanation: The large groups are "ddd", "eeee", and "bbb".👨💻 Алгоритм: 1⃣Поддерживайте указатели i и j, где i <= j. Указатель i представляет начало текущей группы, а j будет инкрементироваться вперед, пока не достигнет конца группы. 2⃣Когда j достигнет конца строки или S[j] != S[j+1], у нас будет группа [i, j]. Если длина группы больше или равна 3, добавьте её в результат. 3⃣Обновите i = j + 1 и начните новую группу. 😎 Решение:
class Solution {
/**
* @param String $S
* @return Integer[][]
*/
function largeGroupPositions($S) {
$ans = [];
$i = 0;
$N = strlen($S);
for ($j = 0; $j < $N; ++$j) {
if ($j == $N - 1 || $S[$j] != $S[$j + 1]) {
if ($j - $i + 1 >= 3) {
$ans[] = [$i, $j];
}
$i = $j + 1;
}
}
return $ans;
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 34. Find First and Last Position of Element in Sorted Array
Сложность: medium
Дан массив
nums, отсортированный в порядке неубывания, и число target. Необходимо найти начальную и конечную позицию target в nums.
Если target не найден, вернуть [-1, -1].
Алгоритм должен работать за O(log n).
Пример:
Input: nums = [5,7,7,8,8,10], target = 8 Output: [3,4]👨💻 Алгоритм: 1⃣Используем бинарный поиск, чтобы найти первое вхождение
target.
2⃣Аналогично находим последнее вхождение target.
3⃣Возвращаем найденные индексы или [-1, -1], если target отсутствует.
😎 Решение:
class Solution {
function searchRange($nums, $target) {
return [$this->binarySearch($nums, $target, true), $this->binarySearch($nums, $target, false)];
}
function binarySearch($nums, $target, $findFirst) {
$left = 0;
$right = count($nums) - 1;
$index = -1;
while ($left <= $right) {
$mid = intdiv($left + $right, 2);
if ($nums[$mid] == $target) {
$index = $mid;
if ($findFirst) {
$right = $mid - 1;
} else {
$left = $mid + 1;
}
} elseif ($nums[$mid] < $target) {
$left = $mid + 1;
} else {
$right = $mid - 1;
}
}
return $index;
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 1209. Remove All Adjacent Duplicates in String II
Сложность: medium
Вам дана строка s и целое число k. Удаление k дубликатов состоит в выборе k соседних и одинаковых букв из s и их удалении, что приводит к соединению левой и правой части удаленной подстроки вместе.
Мы повторяем удаление k дубликатов в s до тех пор, пока не сможем больше этого сделать.
Верните итоговую строку после всех таких удалений дубликатов. Гарантируется, что ответ уникален.
Пример:
Input: s = "deeedbbcccbdaa", k = 3 Output: "aa" Explanation: First delete "eee" and "ccc", get "ddbbbdaa" Then delete "bbb", get "dddaa" Finally delete "ddd", get "aa"👨💻 Алгоритм: 1⃣ Инициализировать медленный указатель j значением 0 и стек counts для хранения количества одинаковых символов. 2⃣Перемещать быстрый указатель i по строке s: Копировать s[i] в s[j]. Если s[j] совпадает с s[j - 1], увеличить значение на вершине стека. Иначе добавить 1 в стек. Если количество символов равно k, уменьшить j на k и извлечь из стека. 3⃣Вернуть первые j символов строки. 😎 Решение:
class Solution {
function removeDuplicates($s, $k) {
$counts = [];
$sa = str_split($s);
$j = 0;
for ($i = 0; $i < count($sa); ++$i, ++$j) {
$sa[$j] = $sa[$i];
if ($j == 0 || $sa[$j] != $sa[$j - 1]) {
array_push($counts, 1);
} else {
$incremented = array_pop($counts) + 1;
if ($incremented == $k) {
$j -= $k;
} else {
array_push($counts, $incremented);
}
}
}
return implode('', array_slice($sa, 0, $j));
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 187. Repeated DNA Sequences
Сложность: medium
ДНК состоит из серии нуклеотидов, обозначаемых как 'A', 'C', 'G' и 'T'.
Например, "ACGAATTCCG" — это последовательность ДНК.
При изучении ДНК полезно определять повторяющиеся последовательности внутри молекулы ДНК.
Дана строка s, представляющая последовательность ДНК. Верните все последовательности длиной 10 букв (подстроки), которые встречаются более одного раза в молекуле ДНК. Ответ можно возвращать в любом порядке.
Пример:
Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT" Output: ["AAAAACCCCC","CCCCCAAAAA"]👨💻 Алгоритм: 1⃣Перебираем начальные позиции последовательности от 1 до 𝑁−𝐿, где 𝑁 — длина строки, а 𝐿 — длина подстроки (в данном случае 10): Если начальная позиция 𝑠𝑡𝑎𝑟𝑡==0, вычисляем хеш первой последовательности 𝑠[0:𝐿]. В противном случае вычисляем скользящий хеш из предыдущего значения хеша. 2⃣Проверяем хеш в хешсете: Если хеш уже существует в хешсете, значит, мы нашли повторяющуюся последовательность, и пора обновить вывод. В противном случае добавляем хеш в хешсет. 3⃣Возвращаем список вывода, содержащий все повторяющиеся последовательности. 😎 Решение:
class Solution {
function findRepeatedDnaSequences($s) {
$L = 10; $n = strlen($s);
if ($n <= $L) return [];
$a = 4; $aL = pow($a, $L);
$toInt = ['A' => 0, 'C' => 1, 'G' => 2, 'T' => 3];
$nums = array_map(function($c) use ($toInt) { return $toInt[$c]; }, str_split($s));
$h = 0;
$seen = []; $output = [];
for ($start = 0; $start < $n - $L + 1; ++$start) {
if ($start != 0)
$h = $h * $a - $nums[$start - 1] * $aL + $nums[$start + $L - 1];
else
for ($i = 0; $i < $L; ++$i)
$h = $h * $a + $nums[$i];
if (in_array($h, $seen))
$output[] = substr($s, $start, $L);
$seen[] = $h;
}
return array_unique($output);
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 1021. Remove Outermost Parentheses
Сложность: easy
Например, "", "()", "(" + A + ")" или A + B, где A и B - допустимые строки со скобками, а + означает объединение строк. Все допустимые строки со скобками - "", "()", "(())()" и "(()(())".
Допустимая строка со скобками s является примитивной, если она непустая и не существует способа разбить ее на s = A + B, причем A и B - непустые допустимые строки со скобками. Если дана допустимая строка со скобками s, рассмотрим ее примитивное разложение: s = P1 + P2 + ... + Pk, где Pi - примитивные допустимые строки со скобками. Верните s после удаления крайних скобок из каждой примитивной строки в примитивном разложении s.
Пример:
Input: s = "(()())(())" Output: "()()()"👨💻 Алгоритм: 1⃣Инициализация переменных: Создайте пустую строку для хранения результата. Используйте счетчик для отслеживания уровня вложенности скобок.. 2⃣Обработка строки: Итерируйте по каждому символу строки. Если встречаете (, увеличивайте счетчик уровня вложенности. Если уровень вложенности больше 1, добавьте ( в результат. Если встречаете ), уменьшайте счетчик уровня вложенности. Если уровень вложенности больше 0 перед уменьшением, добавьте ) в результат. 3⃣Возврат результата: Верните результат, содержащий строку без крайних скобок из каждой примитивной строки. 😎 Решение:
class Solution {
function removeOuterParentheses($s) {
$result = '';
$level = 0;
for ($i = 0; $i < strlen($s); $i++) {
if ($s[$i] == '(') {
if ($level > 0) {
$result .= $s[$i];
}
$level++;
} else {
$level--;
if ($level > 0) {
$result .= $s[$i];
}
}
}
return $result;
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Осталось 3 часа до конца акции:
«Пожизненный PRO тариф — по цене 1 года»
Поиск работы отнимает силы, время и веру в себя, но не у тех кто использует easyoffer PRO. Успей сделать самую выгодную инвестицию в развитие своей карьеры.
Акция закончится уже сегодня 23 июня 23:59 по мск:
👉 https://easyoffer.ru/pro
1 356
Задача: 946. Validate Stack Sequences
Сложность: medium
Учитывая, что два целочисленных массива pushed и popped имеют разные значения, верните true, если это могло быть результатом последовательности операций push и pop на изначально пустом стеке, или false в противном случае.
Пример:
Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1] Output: true👨💻 Алгоритм: 1⃣Инициализировать пустой стек. Использовать указатель j для отслеживания текущей позиции в массиве popped. 2⃣Пройти по каждому элементу в массиве pushed: Добавить элемент в стек. Проверить верхний элемент стека: Если он совпадает с текущим элементом в popped, удалить элемент из стека и увеличить указатель j. 3⃣В конце вернуть true, если указатель j достиг конца массива popped, иначе вернуть false. 😎 Решение:
function validateStackSequences($pushed, $popped) {
$stack = [];
$j = 0;
foreach ($pushed as $x) {
$stack[] = $x;
while (!empty($stack) && $j < count($popped) && end($stack) == $popped[$j]) {
array_pop($stack);
$j++;
}
}
return $j == count($popped);
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Последний день акции:
«Пожизненный PRO тариф — по цене 1 года»
🚀 PRO включает:
– Полный доступ ко всем грейдам и профессиям
– База live-coding задач и вопросов из технических собеседований с вероятностью их встречи
– Примеры лучших ответов от Senior разработчиков
– 1100+ записи реальных собеседований, в том числе в топовые компании (Сбер, Авито, Яндекс, WB, OZON, МТС и др.)
– База 400+ тестовых заданий от компаний.
– Автоотклики на вакансии в хедхантер
– Аналитика ТОП-требований из вакансий для лучшего написания резюме и прохождения ATS систем рекрутеров
– Генератор уникального резюме и CV под каждую вакансию
– Тренажеры подготовки к собеседованию: «Реальное собеседование» и «Проработка вопросов» по методике интервальных повторений (как Anki)
– (скоро) Агрегатор вакансий
– (скоро) Сообщество
Акция закончится уже сегодня 23 июня 23:59 по мск:
👉 https://easyoffer.ru/pro
1 356
Задача: 146. LRU Cache
Сложность: medium
Реализуйте класс LRUCache:
LRUCache(int capacity) - инициализирует LRU-кэш с положительным размером capacity.
int get(int key) - возвращает значение по ключу, если ключ существует, в противном случае возвращает -1.
void put(int key, int value) - обновляет значение по ключу, если ключ существует. В противном случае добавляет пару ключ-значение в кэш. Если количество ключей превышает установленную емкость после этой операции, удаляет наименее недавно использованный ключ.
Функции get и put должны выполняться за среднее время O(1).
Пример:
Input
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]
👨💻 Алгоритм:
1⃣Метод добавления узла в конец связного списка (add):
Получите текущий узел в конце списка, это "реальный" хвост: tail.prev, обозначим его как previousEnd.
Вставьте node после previousEnd, установив previousEnd.next = node.
Настройте указатели узла: node.prev = previousEnd и node.next = tail.
Обновите tail.prev = node, делая node новым "реальным" хвостом списка.
2⃣Метод удаления узла из связного списка (remove):
Узел node должен быть удален из списка. Для этого определите узлы nextNode = node.next и prevNode = node.prev.
Чтобы удалить node, переназначьте prevNode.next = nextNode и nextNode.prev = prevNode, эффективно исключая node из списка.
Это превратит, например, последовательность A <-> B <-> C в A <-> C, где prevNode = A и nextNode = C.
3⃣Методы get и put:
get(int key): Проверьте, существует ли ключ в хэш-карте. Если нет, верните -1. Иначе, получите узел, связанный с ключом, переместите его в конец списка с помощью remove(node) и add(node). Верните node.val.
put(int key, int value): Если ключ уже существует, найдите соответствующий узел и удалите его методом remove. Создайте новый узел с key и value, добавьте его в хэш-карту и в конец списка методом add(node). Если размер кэша превышает установленную емкость после добавления, удалите самый редко используемый узел (который находится в голове списка после фиктивного узла head), затем удалите соответствующий ключ из хэш-карты.
😎 Решение:
class Node {
public $key;
public $value;
public $next;
public $prev;
public function __construct($key, $value) {
$this->key = $key;
$this->value = $value;
$this->next = null;
$this->prev = null;
}
}
class LRUCache {
private $capacity;
private $dic = [];
private $head;
private $tail;
public function __construct($capacity) {
$this->capacity = $capacity;
$this->head = new Node(-1, -1);
$this->tail = new Node(-1, -1);
$this->head->next = $this->tail;
$this->tail->prev = $this->head;
}
public function get($key) {
if (!array_key_exists($key, $this->dic)) {
return -1;
}
$node = $this->dic[$key];
$this->remove($node);
$this->add($node);
return $node->value;
}
public function put($key, $value) {
if (array_key_exists($key, $this->dic)) {
$this->remove($this->dic[$key]);
}
$node = new Node($key, $value);
$this->add($node);
$this->dic[$key] = $node;
if (count($this->dic) > $this->capacity) {
$nodeToDelete = $this->head->next;
$this->remove($nodeToDelete);
unset($this->dic[$nodeToDelete->key]);
}
}
private function add($node) {
$pre = $this->tail->prev;
$pre->next = $node;
$node->prev = $pre;
$node->next = $this->tail;
$this->tail->prev = $node;
}
private function remove($node) {
$pre = $node->prev;
$nxt = $node->next;
$pre->next = $nxt;
$nxt->prev = $pre;
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Пожизненный PRO тариф — по цене 1 года.
Покупаешь один раз — пользуешься всю жизнь:
👉 https://easyoffer.ru/pro
🚀 PRO-доступ закроет 99% проблем на пути к офферу:
1. Полный доступ ко всем грейдам и профессиям. Не важно, Junior вы или Senior, Тестировщик, Разработчик, Проджект — вы получите материалы под ваш текущий уровень и цели, без ограничений.
2. База live-coding задач и вопросов с реальных собесов с уникальной системой вероятности их встречи. Вы будете готовиться не вслепую, а точечно по тем темам, которые спрашивают чаще всего.
3. Эталонные ответы от Senior-разработчиков. Никакой воды и догадок — только четкие, структурированные решения, за которые дают «зеленый свет» к офферу
4. 1100+ записей реальных собеседований (включая топы: Сбер, Авито, Яндекс, WB, OZON, МТС). Вы увидите всё изнутри: как спрашивают, как отвечают сильные кандидаты и на каких ошибках проваливаются 80% проходящих.
5. База 400+ тестовых заданий. Если вы еще студент, то практикуйтесь на решении задач, которые помогут попасть на собес
6. Автоотклики на Хедхантере — пока вы спите, ваше резюме летит к рекрутерам автоматически. Это экономия сотен часов ручного кликанья.
7. Аналитика ТОП-требований из вакансий. Мы парсим рынок и показываем, какие скиллы сейчас в цене. Это позволит вам точечно апгрейдить резюме и проходить суровые ATS-фильтры (которые отсеивают до 75% резюме еще до просмотра рекрутером).
8. Генератор уникального резюме и CV под каждую вакансию. Забудьте про «универсальное» резюме — нейросеть адаптирует ваш опыт под конкретную позицию за минуту, повышая шансы на приглашение в разы.
9. Тренажеры подготовки к собеседованию:
«Реальное собеседование» — сценарий вопросов из реальных интервью
«Проработка вопросов» — флеш карточки с вопросами/ответами по методике интервальных повторений (как Anki)
10. (Скоро) Агрегатор вакансий — все вакансии из HH, Telegram, LinkedIn и других площадок в одной ленте.
11. (Скоро) Закрытое комьюнити — нетворкинг и помощь в сложных вопросах от таких же целеустремленных айтишников.
Завтра последний день акции:
👉 https://easyoffer.ru/pro
1 356
Задача: 686. Repeated String Match
Сложность: medium
Даны две строки a и b. Верните минимальное количество повторений строки a, чтобы строка b стала её подстрокой. Если сделать b подстрокой a невозможно, верните -1.
Обратите внимание: строка "abc", повторенная 0 раз, это "", повторенная 1 раз - "abc", повторенная 2 раза - "abcabc".
Пример:
Input: a = "abcd", b = "cdabcdab"
Output: 3
Explanation: We return 3 because by repeating a three times "abcdabcdabcd", b is a substring of it.
👨💻 Алгоритм:
1⃣Найти минимальное количество повторений строки A, чтобы её длина стала больше или равна длине B. Это значение q = ceil(len(B) / len(A)).
2⃣Проверить, является ли B подстрокой строки A, повторенной q раз. Если да, вернуть q. Иначе, проверить строку A, повторенную (q+1) раз. Если B является подстрокой этой строки, вернуть q+1.
3⃣Если B не является подстрокой ни в одном из случаев, вернуть -1.
😎 Решение:
class Solution {
function repeatedStringMatch($A, $B) {
$q = 1;
$S = $A;
while (strlen($S) < strlen($B)) {
$S .= $A;
$q++;
}
if (strpos($S, $B) !== false) return $q;
if (strpos($S . $A, $B) !== false) return $q + 1;
return -1;
}
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Задача: 1275. Find Winner on a Tic Tac Toe Game
Сложность: easy
В игру "Крестики-нолики" играют два игрока A и B на сетке 3 x 3. Правила игры "Крестики-нолики" таковы: игроки по очереди помещают символы в пустые квадраты ' '. Первый игрок A всегда помещает символы "X", а второй игрок B - "O". Символы "X" и "O" всегда помещаются в пустые квадраты, а не в заполненные.
Игра заканчивается, когда три одинаковых (непустых) символа заполняют любую строку, столбец или диагональ. Игра также заканчивается, если все клетки непустые. Больше ходов не может быть сыграно, если игра закончена. Учитывая двумерный целочисленный массив moves, где moves[i] = [rowi, coli] указывает, что i-й ход будет сыгран на сетке[rowi][coli]. верните победителя игры, если он существует (A или B). Если игра закончилась вничью, верните "Ничья". Если еще есть ходы для игры, верните "Pending". Можно предположить, что ходы действительны (т.е. соответствуют правилам игры в Крестики-нолики), сетка изначально пуста, и A будет играть первым.
Пример:
Input: moves = [[0,0],[2,0],[1,1],[2,1],[2,2]] Output: "A"👨💻 Алгоритм: 1⃣Инициализируйте пустую 3x3 сетку. 2⃣Пройдите по списку ходов и обновите сетку в соответствии с ходами игроков A и B. 3⃣После каждого хода проверяйте, есть ли победитель. Если все ходы сделаны и нет победителя, проверьте, завершена ли игра вничью или еще есть ходы. 😎 Решение:
function tictactoe($moves) {
$grid = array_fill(0, 3, array_fill(0, 3, ''));
for ($i = 0; $i < count($moves); $i++) {
$r = $moves[$i][0];
$c = $moves[$i][1];
$grid[$r][$c] = $i % 2 == 0 ? 'X' : 'O';
}
for ($i = 0; $i < 3; $i++) {
if ($grid[$i][0] == $grid[$i][1] && $grid[$i][1] == $grid[$i][2] && $grid[$i][0] != '')
return $grid[$i][0] == 'X' ? 'A' : 'B';
if ($grid[0][$i] == $grid[1][$i] && $grid[1][$i] == $grid[2][$i] && $grid[0][$i] != '')
return $grid[0][$i] == 'X' ? 'A' : 'B';
}
if ($grid[0][0] == $grid[1][1] && $grid[1][1] == $grid[2][2] && $grid[0][0] != '')
return $grid[0][0] == 'X' ? 'A' : 'B';
if ($grid[0][2] == $grid[1][1] && $grid[1][1] == $grid[2][0] && $grid[0][2] != '')
return $grid[0][2] == 'X' ? 'A' : 'B';
return count($moves) == 9 ? 'Draw' : 'Pending';
}
Ставь 👍 и забирай 📚 Базу знаний1 356
Привет, ребята!
У нас для вас отличные новости — на easyoffer вышло сразу несколько крупных обновлений:
1. Автоотклики на HeadHunter
Снова работают в полную силу — можно смело возвращаться к активному поиску.
2. Новый раздел «Резюмейкер»
Теперь вы можете быстро создавать уникальные резюме, адаптированные под каждую вакансию, и сразу добавлять сопроводительное письмо. Это заметно повышает шансы получить приглашение на собеседование.
3. База вопросов стала чище
Мы навели порядок и удалили около 30% дубликатов.
Ориентироваться стало проще.
––––––––––––––––––
🔥 Акция в честь обновления
Пожизненный тариф easyoffer PRO — по цене одного года.
Успейте до 23 июня:
👉 https://easyoffer.ru/pro
––––––––––––––––––
Что дальше?
В ближайшие пару недель добавим ещё два раздела:
1. Сообщество с чатами по всем профессиональным направлениям.
2. Агрегатор вакансий, чтобы поиск работы стал ещё удобнее.
