PHP | LeetCode
Open in Telegram
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @sendme_ads
Show more1 327
Subscribers
-124 hours
No data7 days
-1830 days
Loading data
Similar Channels
Tags Cloud
Incoming and Outgoing Mentions
---
---
---
---
---
---
Attracting Subscribers
October '26Oct '26
October '26
+3
in 0 channels
September '26
+10
in 0 channels
Get PRO
August '26
+12
in 0 channels
Get PRO
July '26
+6
in 0 channels
Get PRO
June '26
+10
in 1 channels
Get PRO
May '26
+8
in 0 channels
Get PRO
April '26
+1
in 0 channels
Get PRO
March '26
+8
in 0 channels
Get PRO
February '26
+10
in 0 channels
Get PRO
January '26
+12
in 0 channels
Get PRO
December '25
+13
in 0 channels
Get PRO
November '25
+53
in 0 channels
Get PRO
October '25
+34
in 0 channels
Get PRO
September '25
+34
in 0 channels
Get PRO
August '25
+42
in 0 channels
Get PRO
July '25
+48
in 1 channels
Get PRO
June '25
+41
in 0 channels
Get PRO
May '25
+56
in 0 channels
Get PRO
April '25
+53
in 0 channels
Get PRO
March '25
+127
in 3 channels
Get PRO
February '25
+88
in 1 channels
Get PRO
January '25
+98
in 53 channels
Get PRO
December '24
+40
in 0 channels
Get PRO
November '24
+53
in 1 channels
Get PRO
October '24
+152
in 12 channels
Get PRO
September '24
+430
in 331 channels
Get PRO
August '24
+85
in 0 channels
Get PRO
July '24
+382
in 219 channels
Get PRO
June '24
+418
in 232 channels
| Date | Subscriber Growth | Mentions | Channels | |
| 26 October | 0 | |||
| 25 October | 0 | |||
| 24 October | 0 | |||
| 23 October | 0 | |||
| 22 October | 0 | |||
| 21 October | 0 | |||
| 20 October | +1 | |||
| 19 October | 0 | |||
| 18 October | 0 | |||
| 17 October | 0 | |||
| 16 October | 0 | |||
| 15 October | 0 | |||
| 14 October | +1 | |||
| 13 October | 0 | |||
| 12 October | 0 | |||
| 11 October | +1 | |||
| 10 October | 0 | |||
| 09 October | 0 | |||
| 08 October | 0 | |||
| 07 October | 0 | |||
| 06 October | 0 | |||
| 05 October | 0 | |||
| 04 October | 0 | |||
| 03 October | 0 | |||
| 02 October | 0 | |||
| 01 October | 0 |
Channel Posts
Задача: 315. Count of Smaller Numbers After Self
Сложность: hard
Дан целочисленный массив nums, верните целочисленный массив counts, где counts[i] - это количество элементов справа от nums[i], которые меньше nums[i].
Пример:
Input: nums = [5,2,6,1] Output: [2,1,1,0] Explanation: To the right of 5 there are 2 smaller elements (2 and 1). To the right of 2 there is only 1 smaller element (1). To the right of 6 there is 1 smaller element (1). To the right of 1 there is 0 smaller element.👨💻 Алгоритм: 1⃣Реализуйте дерево отрезков (segment tree). Поскольку дерево инициализируется нулями, нужно реализовать только операции обновления и запроса. Установите смещение offset = 10^4. 2⃣Итерация по каждому числу в nums в обратном порядке. Для каждого числа выполните следующие действия: Смещайте число на num + offset. Запросите количество элементов в дереве отрезков, которые меньше текущего числа. Обновите счетчик текущего числа в дереве отрезков. 3⃣Верните результат. 😎 Решение:
class Solution {
function countSmaller($nums) {
$offset = 10000;
$size = 2 * 10000 + 1;
$tree = array_fill(0, $size * 2, 0);
$result = [];
for ($i = count($nums) - 1; $i >= 0; $i--) {
$smallerCount = $this->query(0, $nums[$i] + $offset, $tree, $size);
$result[] = $smallerCount;
$this->update($nums[$i] + $offset, 1, $tree, $size);
}
return array_reverse($result);
}
function update($index, $value, &$tree, $size) {
$index += $size;
$tree[$index] += $value;
while ($index > 1) {
$index = intdiv($index, 2);
$tree[$index] = $tree[$index * 2] + $tree[$index * 2 + 1];
}
}
function query($left, $right, &$tree, $size) {
$result = 0;
$left += $size;
$right += $size;
while ($left < $right) {
if ($left % 2 == 1) {
$result += $tree[$left];
$left++;
}
$left = intdiv($left, 2);
if ($right % 2 == 1) {
$right--;
$result += $tree[$right];
}
$right = intdiv($right, 2);
}
return $result;
}
}
Ставь 👍 и забирай 📚 Базу знаний| 2 | Задача: 1166. Design File System
Сложность: medium
Вам нужно разработать файловую систему, которая позволяет создавать новые пути и связывать их с различными значениями.
Формат пути - это одна или несколько конкатенированных строк в форме: /, за которой следует одна или несколько строчных английских букв. Например, "/leetcode" и "/leetcode/problems" - допустимые пути, в то время как пустая строка "" и "/" не допустимы.
Реализуйте класс FileSystem:
- bool createPath(string path, int value) создает новый путь и связывает с ним значение, если это возможно, и возвращает true. Возвращает false, если путь уже существует или его родительский путь не существует.
- int get(string path) возвращает значение, связанное с путем, или возвращает -1, если путь не существует.
Пример:
Input:
["FileSystem","createPath","get"]
[[],["/a",1],["/a"]]
Output:
[null,true,1]
Explanation:
FileSystem fileSystem = new FileSystem();
fileSystem.createPath("/a", 1); // return true
fileSystem.get("/a"); // return 1
👨💻 Алгоритм:
1⃣Инициализируйте словарь или HashMap под названием paths, который будет использовать ключ в виде пути, переданного в нашу функцию create, и значение, переданное этой функции.
2⃣Для функции create выполняем три шага. Сначала выполняем базовую проверку валидности пути. Проверяем, является ли путь пустым, "/" или если путь уже существует в нашем словаре. Если любое из этих условий выполнено, просто возвращаем false. Затем получаем родительский путь предоставленного пути и проверяем его наличие в словаре. Если родительский путь не существует, возвращаем false, иначе продолжаем.
3⃣Наконец, вставляем предоставленный путь и значение в словарь и возвращаем true. Для функции get просто возвращаем значение по умолчанию -1, если путь не существует в словаре. В противном случае возвращаем фактическое значение.
😎 Решение:
class FileSystem {
private $paths;
function __construct() {
$this->paths = array();
}
function createPath($path, $value) {
if (empty($path) || (strlen($path) == 1 && $path == "/") || array_key_exists($path, $this->paths)) {
return false;
}
$delimIndex = strrpos($path, "/");
$parent = substr($path, 0, $delimIndex);
if (strlen($parent) > 1 && !array_key_exists($parent, $this->paths)) {
return false;
}
$this->paths[$path] = $value;
return true;
}
function get($path) {
return array_key_exists($path, $this->paths) ? $this->paths[$path] : -1;
}
}
Ставь 👍 и забирай 📚 Базу знаний | 39 |
| 3 | Задача: 1663. Smallest String With A Given Numeric Value
Сложность: medium
Числовое значение строчной буквы определяется ее позицией (начиная с 1) в алфавите, поэтому числовое значение a равно 1, числовое значение b равно 2, числовое значение c равно 3 и так далее.
Числовое значение строки, состоящей из строчных букв, определяется как сумма числовых значений ее символов. Например, числовое значение строки "abe" равно 1 + 2 + 5 = 8.
Вам даны два целых числа n и k. Верните лексикографически наименьшую строку длиной n с числовым значением, равным k.
Обратите внимание, что строка x лексикографически меньше строки y, если x идет перед y в словарном порядке, то есть либо x является префиксом y, либо, если i - первая позиция, где x[i] != y[i], то x[i] идет перед y[i] в алфавитном порядке.
Пример:
Input: n = 3, k = 27
Output: "aay"
Explanation: The numeric value of the string is 1 + 1 + 25 = 27, and it is the smallest string with such a value and length equal to 3.
👨💻 Алгоритм:
1⃣Построить строку или массив символов result для хранения выбранных символов для каждой позиции.
2⃣Итерация от позиции 1 до n и заполнение символом каждой позиции:
Найти позиции, которые нужно заполнить, исключая текущую позицию, задаваемую переменной positionsLeft как n - position - 1.
Если значение k больше, чем positionsLeft * 26, зарезервировать числовое значение 26 (символ z) для всех оставшихся позиций positionsLeft. Вычислить значение текущей позиции, заданное переменной add, как k - (positionsLeft * 26). Вычесть рассчитанное значение add из k, чтобы найти оставшееся значение k после заполнения текущей позиции.
Иначе, заполнить текущую позицию символом a, имеющим числовое значение 1. Вычесть 1 из k, чтобы найти оставшееся значение k после заполнения текущей позиции.
3⃣Повторять процесс, пока все позиции не будут заполнены.
😎 Решение:
class Solution {
function getSmallestString($n, $k) {
$result = array_fill(0, $n, 'a');
for ($position = 0; $position < $n; $position++) {
$positionsLeft = ($n - $position - 1);
if ($k > $positionsLeft * 26) {
$add = $k - ($positionsLeft * 26);
$result[$position] = chr(97 + $add - 1);
$k -= $add;
} else {
$k -= 1;
}
}
return implode('', $result);
}
}
Ставь 👍 и забирай 📚 Базу знаний | 73 |
| 4 | Задача: 732. My Calendar III
Сложность: hard
k-бронирование происходит, когда k событий имеют некоторое непустое пересечение (т.е, дано некоторое время, общее для всех k событий). Даны некоторые события [startTime, endTime), после каждого данного события верните целое число k, представляющее максимальное k-бронирование между всеми предыдущими событиями. Реализация класса MyCalendarThree: MyCalendarThree() Инициализирует объект. int book(int startTime, int endTime) Возвращает целое число k, представляющее наибольшее целое число, при котором в календаре существует k-бронирование.
Пример:
Input
["MyCalendarThree", "book", "book", "book", "book", "book", "book"]
[[], [10, 20], [50, 60], [10, 40], [5, 15], [5, 10], [25, 55]]
Output
[null, 1, 1, 2, 3, 3, 3]
👨💻 Алгоритм:
1⃣Создайте два словаря для хранения изменений времени бронирования: один для начала событий, другой для конца событий.
2⃣Для каждого нового события обновите словари начала и конца событий.
3⃣Поддерживайте текущее количество активных бронирований и обновляйте максимальное количество активных бронирований по мере добавления новых событий.
😎 Решение:
class MyCalendarThree {
private $events;
function __construct() {
$this->events = [];
}
function book($startTime, $endTime) {
if (!isset($this->events[$startTime])) {
$this->events[$startTime] = 0;
}
if (!isset($this->events[$endTime])) {
$this->events[$endTime] = 0;
}
$this->events[$startTime]++;
$this->events[$endTime]--;
ksort($this->events);
$active = 0;
$maxActive = 0;
foreach ($this->events as $time => $count) {
$active += $count;
$maxActive = max($maxActive, $active);
}
return $maxActive;
}
}
Ставь 👍 и забирай 📚 Базу знаний | 66 |
| 5 | 🔥 Скрытые вакансии с удаленной работой для PHP разработчика, которые нигде больше не публикуются. Напрямую от компаний, с контактами рекрутеров.
🔹 PHP Jobs | Вакансии
🔸 Все каналы с вакансиями | 84 |
| 6 | Задача: 943. Find the Shortest Superstring
Сложность: hard
Учитывая массив строк words, верните наименьшую строку, которая содержит каждую строку в words в качестве подстроки. Если существует несколько допустимых строк наименьшей длины, верните любую из них. Вы можете предположить, что ни одна строка в words не является подстрокой другой строки в words.
Пример:
Input: words = ["alex","loves","leetcode"]
Output: "alexlovesleetcode"
👨💻 Алгоритм:
1⃣Реализовать функцию overlap для вычисления максимального перекрытия двух строк, где одна строка заканчивается, а другая начинается.
2⃣Реализовать функцию merge для объединения двух строк с максимальным перекрытием.
Использовать жадный алгоритм для нахождения двух строк с максимальным перекрытием и объединить их, повторяя до тех пор, пока не останется одна строка.
3⃣Вернуть результат.
😎 Решение:
function shortestSuperstring($words) {
while (count($words) > 1) {
$maxOverlap = -1;
$l = 0;
$r = 0;
$merged = '';
for ($i = 0; $i < count($words); $i++) {
for ($j = 0; $j < count($words); $j++) {
if ($i != $j) {
$ovlp = overlap($words[$i], $words[$j]);
if ($ovlp > $maxOverlap) {
$maxOverlap = $ovlp;
$l = $i;
$r = $j;
$merged = merge($words[$i], $words[$j], $ovlp);
}
}
}
}
$words[$l] = $merged;
array_splice($words, $r, 1);
}
return $words[0];
}
function overlap($a, $b) {
$maxOverlap = 0;
for ($i = 1; $i <= min(strlen($a), strlen($b)); $i++) {
if (substr($a, -$i) === substr($b, 0, $i)) {
$maxOverlap = $i;
}
}
return $maxOverlap;
}
function merge($a, $b, $overlapLen) {
return $a . substr($b, $overlapLen);
}
Ставь 👍 и забирай 📚 Базу знаний | 99 |
| 7 | Задача: 349. Intersection of Two Arrays
Сложность: easy
Даны два целочисленных массива nums1 и nums2. Верните массив их пересечения. Каждый элемент в результате должен быть уникальным, и вы можете вернуть результат в любом порядке.
Пример:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2]
👨💻 Алгоритм:
1⃣Создание множеств:
Преобразуйте оба массива nums1 и nums2 в множества для получения уникальных элементов.
2⃣Нахождение пересечения:
Найдите пересечение двух множеств.
3⃣Возврат результата:
Преобразуйте пересечение обратно в массив и верните его.
😎 Решение:
class Solution {
function intersection($nums1, $nums2) {
$set1 = array_unique($nums1);
$set2 = array_unique($nums2);
$result = array_intersect($set1, $set2);
return array_values($result);
}
}
Ставь 👍 и забирай 📚 Базу знаний | 81 |
| 8 | Задача: 1302. Deepest Leaves Sum
Сложность: medium
Дано корень бинарного дерева, вернуть сумму значений его самых глубоких листьев.
Пример:
Input: root = [1,2,3,4,5,null,6,7,null,null,null,null,8]
Output: 15
👨💻 Алгоритм:
1⃣Поместите корень в стек.
2⃣Пока стек не пуст. Извлеките узел из стека и обновите текущее число. Если узел является листом, обновите сумму самых глубоких листьев deepest_sum. Поместите правый и левый дочерние узлы в стек.
3⃣Верните deepest_sum.
😎 Решение:
class Solution {
function deepestLeavesSum($root) {
$deepestSum = 0;
$depth = 0;
$stack = [[$root, 0]];
while (!empty($stack)) {
list($node, $currDepth) = array_pop($stack);
if ($node->left === null && $node->right === null) {
if ($depth < $currDepth) {
$deepestSum = $node->val;
$depth = $currDepth;
} elseif ($depth == $currDepth) {
$deepestSum += $node->val;
}
} else {
if ($node->right !== null) {
$stack[] = [$node->right, $currDepth + 1];
}
if ($node->left !== null) {
$stack[] = [$node->left, $currDepth + 1];
}
}
}
return $deepestSum;
}
}
Ставь 👍 и забирай 📚 Базу знаний | 69 |
| 9 | Задача: 760. Find Anagram Mappings
Сложность: easy
Вам даны два целочисленных массива nums1 и nums2, где nums2 - анаграмма nums1. Оба массива могут содержать дубликаты. Верните индексное отображение массива mapping из nums1 в nums2, где mapping[i] = j означает, что i-й элемент в nums1 появляется в nums2 по индексу j. Если ответов несколько, верните любой из них. Массив a является анаграммой массива b означает, что b создается путем случайного изменения порядка элементов в a.
Пример:
Input: nums1 = [12,28,46,32,50], nums2 = [50,12,32,46,28]
Output: [1,4,3,2,0]
👨💻 Алгоритм:
1⃣Создайте словарь для хранения индексов элементов в nums2.
2⃣Пройдите по элементам массива nums1 и для каждого элемента найдите соответствующий индекс в nums2, используя словарь.
3⃣Верните массив индексов.
😎 Решение:
function anagramMapping($nums1, $nums2) {
$indexMap = [];
foreach ($nums2 as $i => $num) {
if (!isset($indexMap[$num])) {
$indexMap[$num] = [];
}
$indexMap[$num][] = $i;
}
$mapping = [];
foreach ($nums1 as $num) {
$mapping[] = array_pop($indexMap[$num]);
}
return $mapping;
}
Ставь 👍 и забирай 📚 Базу знаний | 73 |
| 10 | Задача: 474. Ones and Zeroes
Сложность: medium
Дан массив двоичных строк strs и два целых числа m и n.
Верните размер наибольшего подмножества strs, такого что в подмножестве содержится не более m нулей и n единиц.
Множество x является подмножеством множества y, если все элементы множества x также являются элементами множества y.
Пример:
Input: strs = ["10","0001","111001","1","0"], m = 5, n = 3
Output: 4
Explanation: The largest subset with at most 5 0's and 3 1's is {"10", "0001", "1", "0"}, so the answer is 4.
Other valid but smaller subsets include {"0001", "1"} and {"10", "1", "0"}.
{"111001"} is an invalid subset because it contains 4 1's, greater than the maximum of 3.
👨💻 Алгоритм:
1⃣Рассматриваем все возможные подмножества, прерывая цикл, если количество нулей превышает m или количество единиц превышает n.
2⃣Считаем количество нулей и единиц в каждом подмножестве.
3⃣Выбираем наибольшее подмножество, соответствующее условиям, и возвращаем его размер.
😎 Решение:
class Solution {
function findMaxForm($strs, $m, $n) {
$maxlen = 0;
for ($i = 0; $i < (1 << count($strs)); $i++) {
$zeroes = 0;
$ones = 0;
$len = 0;
for ($j = 0; $j < 32; $j++) {
if (($i & (1 << $j)) != 0) {
$count = $this->countZeroesOnes($strs[$j]);
$zeroes += $count[0];
$ones += $count[1];
if ($zeroes > $m || $ones > $n)
break;
$len++;
}
}
if ($zeroes <= $m && $ones <= $n)
$maxlen = max($maxlen, $len);
}
return $maxlen;
}
function countZeroesOnes($s) {
$c = array(0, 0);
for ($i = 0; $i < strlen($s); $i++) {
$c[$s[$i] - '0']++;
}
return $c;
}
}
Ставь 👍 и забирай 📚 Базу знаний | 61 |
| 11 | Задача: 1273. Delete Tree Nodes
Сложность: medium
Дерево, укорененное в узле 0, задано следующим образом: количество узлов - nodes; значение i-го узла - value[i]; родитель i-го узла - parent[i]. Удалите все поддеревья, сумма значений узлов которых равна нулю. Верните количество оставшихся узлов в дереве.
Пример:
Input: nodes = 7, parent = [-1,0,0,1,2,2,2], value = [1,-2,4,0,-2,-1,-1]
Output: 2
👨💻 Алгоритм:
1⃣Постройте дерево из заданных узлов, значений и родителей.
2⃣Используйте постфиксный обход для вычисления суммы значений в каждом поддереве и помечайте узлы для удаления, если их сумма равна нулю.
3⃣Удалите отмеченные узлы и их поддеревья и верните количество оставшихся узлов.
😎 Решение:
function deleteTreeNodes($nodes, $parent, $value) {
$tree = [];
for ($i = 0; $i < $nodes; $i++) {
if (!isset($tree[$parent[$i]])) $tree[$parent[$i]] = [];
$tree[$parent[$i]][] = $i;
}
function dfs($node, &$tree, &$value) {
$totalSum = $value[$node];
$totalCount = 1;
if (isset($tree[$node])) {
foreach ($tree[$node] as $child) {
list($childSum, $childCount) = dfs($child, $tree, $value);
$totalSum += $childSum;
$totalCount += $childCount;
}
}
return $totalSum == 0 ? [0, 0] : [$totalSum, $totalCount];
}
return dfs(0, $tree, $value)[1];
}
Ставь 👍 и забирай 📚 Базу знаний | 72 |
| 12 | Задача: 724. Find Pivot Index
Сложность: easy
Если задан массив целых чисел nums, вычислите поворотный индекс этого массива. Поворотный индекс - это индекс, при котором сумма всех чисел строго слева от индекса равна сумме всех чисел строго справа от индекса. Если индекс находится на левом краю массива, то сумма слева равна 0, так как слева нет элементов. Это относится и к правому краю массива. Возвращается самый левый поворотный индекс. Если такого индекса не существует, возвращается -1.
Пример:
Input: nums = [1,7,3,6,5,6]
Output: 3
👨💻 Алгоритм:
1⃣Вычислите сумму всех элементов массива.
2⃣Пройдите по массиву, вычисляя текущую сумму элементов слева и проверяя, равна ли она разности между общей суммой и текущей суммой справа.
3⃣Если текущий индекс удовлетворяет условию, верните его; если нет, продолжайте проверку. Если такой индекс не найден, верните -1.
😎 Решение:
function pivotIndex($nums) {
$totalSum = array_sum($nums);
$leftSum = 0;
foreach ($nums as $i => $num) {
if ($leftSum == $totalSum - $leftSum - $num) {
return $i;
}
$leftSum += $num;
}
return -1;
}
Ставь 👍 и забирай 📚 Базу знаний | 73 |
| 13 | Задача: 674. Longest Continuous Increasing Subsequence
Сложность: easy
Дан неотсортированный массив целых чисел nums, верните длину самой длинной непрерывной возрастающей подпоследовательности (т.е. подмассива). Подпоследовательность должна быть строго возрастающей.
Непрерывная возрастающая подпоследовательность определяется двумя индексами l и r (l < r) так, что она имеет вид [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] и для каждого l <= i < r выполняется nums[i] < nums[i + 1].
Пример:
Input: nums = [1,3,5,4,7]
Output: 3
Explanation: The longest continuous increasing subsequence is [1,3,5] with length 3.
Even though [1,3,5,7] is an increasing subsequence, it is not continuous as elements 5 and 7 are separated by element
4.
👨💻 Алгоритм:
1⃣Каждая (непрерывная) возрастающая подпоследовательность не пересекается, и граница каждой такой подпоследовательности возникает, когда nums[i-1] >= nums[i]. В этом случае начинается новая возрастающая подпоследовательность с nums[i], и мы сохраняем такой i в переменной anchor.
2⃣Например, если nums = [7, 8, 9, 1, 2, 3], то anchor начинается с 0 (nums[anchor] = 7) и затем устанавливается на anchor = 3 (nums[anchor] = 1). Независимо от значения anchor, мы записываем кандидата на ответ длиной i - anchor + 1, длина подмассива nums[anchor], nums[anchor+1], ..., nums[i], и наш ответ обновляется соответствующим образом.
3⃣Возвращаем максимальную длину найденной непрерывной возрастающей подпоследовательности.
😎 Решение:
class Solution {
function findLengthOfLCIS($nums) {
$ans = 0;
$anchor = 0;
for ($i = 0; $i < count($nums); ++$i) {
if ($i > 0 && $nums[$i - 1] >= $nums[$i]) {
$anchor = $i;
}
$ans = max($ans, $i - $anchor + 1);
}
return $ans;
}
}
Ставь 👍 и забирай 📚 Базу знаний | 72 |
| 14 | Задача: 899. Orderly Queue
Сложность: hard
Вам дана строка s и целое число k. Вы можете выбрать одну из первых k букв s и добавить ее в конец строки. Верните лексикографически наименьшую строку, которая может получиться после применения указанного шага за любое количество ходов.
Пример:
Input: s = "cba", k = 1
Output: "acb"
👨💻 Алгоритм:
1⃣Если k равно 1, найти лексикографически наименьшую строку путем вращения строки и поиска минимального варианта.
2⃣Если k больше 1, отсортировать строку, так как любое количество перемещений позволит упорядочить все символы в строке.
3⃣Вернуть результат.
😎 Решение:
function orderlyQueue($s, $k) {
if ($k == 1) {
$minString = $s;
for ($i = 1; $i < strlen($s); $i++) {
$rotated = substr($s, $i) . substr($s, 0, $i);
if ($rotated < $minString) {
$minString = $rotated;
}
}
return $minString;
} else {
$sArray = str_split($s);
sort($sArray);
return implode('', $sArray);
}
}
Ставь 👍 и забирай 📚 Базу знаний | 80 |
| 15 | Задача: 913. Cat and Mouse4
Сложность: hard
В игру на неориентированном графе играют два игрока, Мышь и Кот, которые чередуются по очереди. Граф задан следующим образом: graph[a] - это список всех вершин b, таких, что ab является ребром графа. Мышь начинает в вершине 1 и идет первой, Кот начинает в вершине 2 и идет второй, а в вершине 0 находится дыра. Во время хода каждого игрока он должен пройти по одному ребру графа, которое встречает его местоположение.Например, если Мышь находится в узле 1, она должна добраться до любого узла графа[1]. Кроме того, Кошке запрещено добираться до Дыры (узел 0). Затем игра может закончиться тремя способами: если Кошка занимает тот же узел, что и Мышь, Кошка побеждает. Если Мышь достигает Дыры, Мышь побеждает. Если позиция повторяется (т.е, игроки находятся в той же позиции, что и в предыдущий ход, и сейчас очередь того же игрока двигаться), то игра считается ничейной. Учитывая граф и предполагая, что оба игрока играют оптимально, верните 1, если в игре победила мышь, 2, если в игре победила кошка, или 0, если в игре ничья.
Пример:
Input: graph = [[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]]
Output: 0
👨💻 Алгоритм:
1⃣Использовать динамическое программирование с мемоизацией для хранения результатов игры для каждой комбинации позиций мыши, кота и текущего игрока.
2⃣Проверить три условия окончания игры:
Мышь достигает дырки (победа мыши).
Кот достигает мыши (победа кота).
Позиция повторяется (ничья).
3⃣Использовать BFS (поиск в ширину) для определения результатов игры, начиная с конечных состояний и работая назад.
😎 Решение:
function catMouseGame($graph) {
$n = count($graph);
$DRAW = 0; $MOUSE = 1; $CAT = 2;
$dp = array_fill(0, $n, array_fill(0, $n, array_fill(0, 2, $DRAW)));
$queue = [];
for ($i = 1; $i < $n; $i++) {
$dp[0][$i][0] = $MOUSE;
$dp[0][$i][1] = $MOUSE;
$dp[$i][$i][0] = $CAT;
$dp[$i][$i][1] = $CAT;
$queue[] = [0, $i, 0, $MOUSE];
$queue[] = [0, $i, 1, $MOUSE];
$queue[] = [$i, $i, 0, $CAT];
$queue[] = [$i, $i, 1, $CAT];
}
function parents($graph, $mouse, $cat, $turn) {
$res = [];
if ($turn == 1) {
foreach ($graph[$mouse] as $m) {
$res[] = [$m, $cat, 0];
}
} else {
foreach ($graph[$cat] as $c) {
if ($c > 0) $res[] = [$mouse, $c, 1];
}
}
return $res;
}
while (!empty($queue)) {
list($mouse, $cat, $turn, $winner) = array_shift($queue);
foreach (parents($graph, $mouse, $cat, $turn) as list($m, $c, $t)) {
if ($dp[$m][$c][$t] == $DRAW) {
if (($t == 0 && $winner == $MOUSE) || ($t == 1 && $winner == $CAT)) {
$dp[$m][$c][$t] = $winner;
$queue[] = [$m, $c, $t, $winner];
} else {
$degrees = 0;
foreach (parents($graph, $m, $c, $t) as $_) $degrees++;
if ($degrees == 0) {
$dp[$m][$c][$t] = $winner;
$queue[] = [$m, $c, $t, $winner];
}
}
}
}
}
return $dp[1][2][0];
}
Ставь 👍 и забирай 📚 Базу знаний | 87 |
| 16 | Задача: 71. Simplify Path
Сложность: medium
Дан абсолютный путь для файловой системы в стиле Unix, который начинается с символа '/'. Преобразуйте этот путь в его упрощенный канонический путь.
В контексте файловой системы Unix-style одинарная точка '.' обозначает текущий каталог, двойная точка '..' означает переход на один уровень каталога вверх, а несколько слэшей, таких как '//', интерпретируются как один слэш. В этой задаче последовательности точек, не охваченные предыдущими правилами (например, '...'), следует рассматривать как допустимые имена для файлов или каталогов.
Упрощенный канонический путь должен соответствовать следующим правилам:
Он должен начинаться с одного слэша '/'.
Каталоги в пути должны быть разделены только одним слэшем '/'.
Он не должен заканчиваться слэшем '/', если только это не корневой каталог.
Он должен исключать любые одинарные или двойные точки, используемые для обозначения текущих или родительских каталогов.
Верните новый путь.
Пример:
Input: path = "/home/"
Output: "/home"
Explanation:
The trailing slash should be removed.
👨💻 Алгоритм:
1⃣Инициализируем стек S, который будет использоваться в нашей реализации. Разделяем входную строку, используя символ '/' в качестве разделителя. Этот шаг очень важен, поскольку входные данные всегда являются допустимым путем, и наша задача — лишь его сократить. Таким образом, все, что находится между двумя символами '/', является либо именем каталога, либо специальным символом, и мы должны соответственно обработать их.
2⃣Как только входной путь разделен, мы обрабатываем каждый компонент по отдельности. Если текущий компонент — это точка '.' или пустая строка, мы ничего не делаем и просто продолжаем. Если вспомнить, массив строк, полученный при разделении строки '/a//b', будет [a, , b], где между a и b находится пустая строка, что в контексте общего пути не имеет значения. Если мы сталкиваемся с двойной точкой '..', это означает, что нужно подняться на один уровень выше в текущем пути каталога. Поэтому мы удаляем запись из нашего стека, если он не пуст.
3⃣Наконец, если обрабатываемый нами в данный момент компонент не является одним из специальных символов, мы просто добавляем его в наш стек, так как это законное имя каталога. Как только все компоненты обработаны, нам просто нужно соединить все имена каталогов в нашем стеке, используя '/' в качестве разделителя, и мы получим самый короткий путь, который приведет нас в тот же каталог, что и предоставленный на входе.
😎 Решение:
function simplifyPath($path) {
$stack = [];
$portions = explode("/", $path);
foreach ($portions as $portion) {
if ($portion === "..") {
if (!empty($stack)) {
array_pop($stack);
}
} elseif ($portion !== "." && $portion !== "") {
array_push($stack, $portion);
}
}
return "/" . implode("/", $stack);
}
Ставь 👍 и забирай 📚 Базу знаний | 86 |
| 17 | 🔥 Скрытые вакансии с удаленной работой для PHP разработчика, которые нигде больше не публикуются. Напрямую от компаний, с контактами рекрутеров.
🔹 PHP Jobs | Вакансии
🔸 Все каналы с вакансиями | 121 |
| 18 | Задача: 166. Fraction to Recurring Decimal
Сложность: medium
Даны два целых числа, представляющих числитель и знаменатель дроби. Верните дробь в строковом формате.
Если дробная часть повторяется, заключите повторяющуюся часть в скобки.
Если возможны несколько ответов, верните любой из них.
Гарантируется, что длина строки ответа будет меньше 10^4 для всех предоставленных входных данных.
Пример:
Input: numerator = 1, denominator = 2
Output: "0.5"
👨💻 Алгоритм:
1⃣Использование хеш-таблицы для отслеживания остатков:
Создайте хеш-таблицу для хранения соответствия между остатком от деления и его позицией в дробной части. Это поможет определить начало повторяющейся части.
Для каждого нового остатка вычислите следующую цифру результата деления и проверьте, был ли такой остаток уже получен ранее.
2⃣Обработка нулевого остатка:
Если в процессе деления остаток становится равным нулю, это означает, что дробная часть не повторяется и процесс можно завершать.
3⃣Учет особенностей:
Будьте осторожны с крайними случаями, такими как отрицательные дроби или особо сложные случаи, например, деление −1 на −2147483648. В этих случаях следует корректно обрабатывать знаки и возможные переполнения.
😎 Решение:
class Solution {
function fractionToDecimal($numerator, $denominator) {
if ($numerator == 0) {
return "0";
}
$fraction = "";
if (($numerator < 0) xor ($denominator < 0)) {
$fraction .= "-";
}
$dividend = abs($numerator);
$divisor = abs($denominator);
$fraction .= intval($dividend / $divisor);
$remainder = $dividend % $divisor;
if ($remainder == 0) {
return $fraction;
}
$fraction .= ".";
$lookup = [];
while ($remainder != 0) {
if (isset($lookup[$remainder])) {
$pos = $lookup[$remainder];
$fraction = substr($fraction, 0, $pos) . "(" . substr($fraction, $pos) . ")";
break;
}
$lookup[$remainder] = strlen($fraction);
$remainder *= 10;
$fraction .= intval($remainder / $divisor);
$remainder %= $divisor;
}
return $fraction;
}
}
Ставь 👍 и забирай 📚 Базу знаний | 112 |
| 19 | Задача: 1024. Video Stitching
Сложность: medium
Вам дана серия видеоклипов со спортивного соревнования, длительность которых составляет несколько секунд. Эти видеоклипы могут накладываться друг на друга и иметь различную длину. Каждый видеоклип описывается массивом clips, где clips[i] = [starti, endi] указывает, что i-й клип начинается в starti и заканчивается в endi. Мы можем произвольно разрезать эти клипы на сегменты. Например, клип [0, 7] может быть разрезан на сегменты [0, 1] + [1, 3] + [3, 7]. Верните минимальное количество клипов, необходимое для того, чтобы мы могли разрезать клипы на сегменты, охватывающие все спортивное событие [0, время]. Если задача невыполнима, верните -1.
Пример:
Input: clips = [[0,2],[4,6],[8,10],[1,9],[1,5],[5,9]], time = 10
Output: 3
👨💻 Алгоритм:
1⃣Сортировка клипов:
Отсортируйте клипы по начальным значениям. Если начальные значения равны, отсортируйте по конечным значениям в убывающем порядке.
2⃣Выбор клипов:
Используйте жадный алгоритм для выбора клипов. Начните с начальной точки 0 и двигайтесь вперед, выбирая клип, который может покрыть наибольший диапазон.
Если обнаруживается, что начальная точка текущего клипа больше текущей позиции, это означает, что клипы не могут покрыть промежуток, и нужно вернуть -1.
3⃣Проверка покрытия:
Продолжайте процесс, пока не покроете весь диапазон от 0 до T. Если в конце процесса достигнута или превышена точка T, верните количество использованных клипов, иначе верните -1.
😎 Решение:
class Solution {
function videoStitching($clips, $T) {
usort($clips, function($a, $b) {
return $a[0] == $b[0] ? $b[1] - $a[1] : $a[0] - $b[0];
});
$end = -1;
$end2 = 0;
$res = 0;
foreach ($clips as $clip) {
if ($end2 >= $T || $clip[0] > $end2) break;
if ($end < $clip[0] && $clip[0] <= $end2) {
$res++;
$end = $end2;
}
$end2 = max($end2, $clip[1]);
}
return $end2 >= $T ? $res : -1;
}
}
Ставь 👍 и забирай 📚 Базу знаний | 96 |
| 20 | Задача: 924. Minimize Malware Spread
Сложность: hard
Вам дана сеть из n узлов, представленная в виде графа с матрицей смежности n x n, где i-й узел непосредственно связан с j-м узлом, если graph[i][j] == 1. Некоторые узлы изначально заражены вредоносным ПО. Если два узла соединены напрямую и хотя бы один из них заражен вредоносным ПО, то оба узла будут заражены вредоносным ПО. Такое распространение вредоносного ПО будет продолжаться до тех пор, пока не останется ни одного узла, который можно было бы заразить таким образом. Предположим, что M(initial) - это конечное число узлов, зараженных вредоносным ПО, во всей сети после прекращения распространения вредоносного ПО. Мы удалим из initial ровно один узел. Верните тот узел, удаление которого минимизирует M(initial). Если можно удалить несколько узлов, чтобы минимизировать M(initial), верните такой узел с наименьшим индексом. Обратите внимание, что если узел был удален из начального списка зараженных узлов, он все равно может быть заражен позже из-за распространения вредоносного ПО.
Пример:
Input: arr = [1,1,2,2,3,3,4,4,5,5], target = 8
Output: 20
👨💻 Алгоритм:
1⃣Определить количество зараженных узлов после распространения вредоносного ПО для исходного списка initial.
2⃣Для каждого узла в initial удалить его и вычислить количество зараженных узлов после распространения вредоносного ПО.
3⃣Найти узел, удаление которого минимизирует количество зараженных узлов. Если есть несколько таких узлов, выбрать узел с наименьшим индексом.
😎 Решение:
function minMalwareSpread($graph, $initial) {
function dfs($graph, $node, &$infected) {
for ($neighbor = 0; $neighbor < count($graph); $neighbor++) {
if ($graph[$node][$neighbor] == 1 && !in_array($neighbor, $infected)) {
$infected[] = $neighbor;
dfs($graph, $neighbor, $infected);
}
}
}
$n = count($graph);
$initialSet = $initial;
sort($initial);
$minInfected = PHP_INT_MAX;
$bestNode = $initial[0];
foreach ($initial as $node) {
$infected = $initialSet;
$infected = array_diff($infected, [$node]);
foreach ($initialSet as $i) {
if ($i != $node) {
dfs($graph, $i, $infected);
}
}
if (count($infected) < $minInfected) {
$minInfected = count($infected);
$bestNode = $node;
}
}
return $bestNode;
}
Ставь 👍 и забирай 📚 Базу знаний | 76 |
