PHP | LeetCode
1.33K subscribers
202 photos
1.4K links
Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy

Контакт для рекламы: @sendme_ads
Download Telegram
Задача: 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;
}
}


Ставь 👍 и забирай 📚 Базу знаний
🔥 Скрытые вакансии с удаленной работой для PHP разработчика, которые нигде больше не публикуются. Напрямую от компаний, с контактами рекрутеров.

🔹 PHP Jobs | Вакансии

🔸 Все каналы с вакансиями
Задача: 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);
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 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];
}


Ставь 👍 и забирай 📚 Базу знаний
👍1
Задача: 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);
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 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;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 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;
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 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];
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 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;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 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;
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 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;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 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);
}
}


Ставь 👍 и забирай 📚 Базу знаний