#hard
Задача: 710. Random Pick with Blacklist
Вам дано целое число n и массив уникальных целых чисел blacklist. Разработайте алгоритм выбора случайного целого числа из диапазона [0, n - 1], не входящего в черный список. Любое целое число, находящееся в указанном диапазоне и не входящее в черный список, должно с равной вероятностью быть возвращено. Оптимизируйте алгоритм так, чтобы он минимизировал количество обращений к встроенной функции random вашего языка. Реализуйте класс Solution: Solution(int n, int[] blacklist) Инициализирует объект целым числом n и целым числом из черного списка blacklist. int pick() Возвращает случайное целое число в диапазоне [0, n - 1] и не входящее в черный список.
Пример:
👨💻 Алгоритм:
1⃣ Создайте маппинг для чисел, входящих в черный список, чтобы сопоставить их с числами из диапазона [n - len(blacklist), n - 1], которые не входят в черный список.
2⃣ Создайте массив для хранения возможных чисел для выбора, исключая числа из черного списка.
3⃣ При каждом вызове функции pick() используйте встроенную функцию random для выбора случайного индекса из массива возможных чисел и возвращайте соответствующее значение.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 710. Random Pick with Blacklist
Вам дано целое число n и массив уникальных целых чисел blacklist. Разработайте алгоритм выбора случайного целого числа из диапазона [0, n - 1], не входящего в черный список. Любое целое число, находящееся в указанном диапазоне и не входящее в черный список, должно с равной вероятностью быть возвращено. Оптимизируйте алгоритм так, чтобы он минимизировал количество обращений к встроенной функции random вашего языка. Реализуйте класс Solution: Solution(int n, int[] blacklist) Инициализирует объект целым числом n и целым числом из черного списка blacklist. int pick() Возвращает случайное целое число в диапазоне [0, n - 1] и не входящее в черный список.
Пример:
Input
["Solution", "pick", "pick", "pick", "pick", "pick", "pick", "pick"]
[[7, [2, 3, 5]], [], [], [], [], [], [], []]
Output
[null, 0, 4, 1, 6, 1, 0, 4]
class Solution {
private $map;
private $bound;
function __construct($n, $blacklist) {
$this->map = [];
$this->bound = $n - count($blacklist);
$blackset = array_flip($blacklist);
$whitelist = $this->bound;
foreach ($blacklist as $b) {
if ($b < $this->bound) {
while (isset($blackset[$whitelist])) {
$whitelist++;
}
$this->map[$b] = $whitelist;
$whitelist++;
}
}
}
function pick() {
$r = rand(0, $this->bound - 1);
return $this->map[$r] ?? $r;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 711. Number of Distinct Islands II
Вам дана двоичная матричная сетка m x n. Остров - это группа 1 (представляющая сушу), соединенных в четырех направлениях (горизонтальном или вертикальном). Можно предположить, что все четыре края сетки окружены водой. Остров считается одинаковым с другим, если они имеют одинаковую форму, или имеют одинаковую форму после поворота (только на 90, 180 или 270 градусов) или отражения (влево/вправо или вверх/вниз). Верните количество разных островов.
Пример:
👨💻 Алгоритм:
1⃣ Пройдите по каждому элементу матрицы, если найдена земля (1), выполните DFS для обнаружения всех связанных с этим островом земель и сохраните форму острова.
2⃣ Нормализуйте форму острова, применив все возможные повороты и отражения, чтобы найти каноническую форму.
3⃣ Используйте множество для хранения всех уникальных канонических форм и верните размер этого множества.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 711. Number of Distinct Islands II
Вам дана двоичная матричная сетка m x n. Остров - это группа 1 (представляющая сушу), соединенных в четырех направлениях (горизонтальном или вертикальном). Можно предположить, что все четыре края сетки окружены водой. Остров считается одинаковым с другим, если они имеют одинаковую форму, или имеют одинаковую форму после поворота (только на 90, 180 или 270 градусов) или отражения (влево/вправо или вверх/вниз). Верните количество разных островов.
Пример:
Input: grid = [[1,1,0,0,0],[1,0,0,0,0],[0,0,0,0,1],[0,0,0,1,1]]
Output: 1
function numDistinctIslands2($grid) {
$uniqueIslands = [];
for ($i = 0; $i < count($grid); $i++) {
for ($j = 0; $j < count($grid[0]); $j++) {
if ($grid[$i][$j] == 1) {
$shape = [];
dfs($grid, $i, $j, $i, $j, $shape);
$uniqueIslands[normalize($shape)] = true;
}
}
}
return count($uniqueIslands);
}
function dfs(&$grid, $i, $j, $baseI, $baseJ, &$shape) {
if ($i < 0 || $i >= count($grid) || $j < 0 || $j >= count($grid[0]) || $grid[$i][$j] == 0) {
return;
}
$grid[$i][$j] = 0;
$shape[] = [$i - $baseI, $j - $baseJ];
dfs($grid, $i + 1, $j, $baseI, $baseJ, $shape);
dfs($grid, $i - 1, $j, $baseI, $baseJ, $shape);
dfs($grid, $i, $j + 1, $baseI, $baseJ, $shape);
dfs($grid, $i, $j - 1, $baseI, $baseJ, $shape);
}
function normalize($shape) {
$shapes = array_fill(0, 8, []);
foreach ($shape as $p) {
$x = $p[0];
$y = $p[1];
$shapes[0][] = [$x, $y];
$shapes[1][] = [$x, -$y];
$shapes[2][] = [-$x, $y];
$shapes[3][] = [-$x, -$y];
$shapes[4][] = [$y, $x];
$shapes[5][] = [$y, -$x];
$shapes[6][] = [-$y, $x];
$shapes[7][] = [-$y, -$x];
}
foreach ($shapes as &$s) {
sort($s);
}
$minShape = implode(",", array_map(function($p) { return implode(",", $p); }, $shapes[0]));
foreach ($shapes as $s) {
$sStr = implode(";", array_map(function($p) { return implode(",", $p); }, $s));
$minShape = min($minShape, $sStr);
}
return $minShape;
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
#hard
Задача: 765. Couples Holding Hands
Есть n пар, сидящих на 2n местах, расположенных в ряд, и они хотят держаться за руки.
Люди и места представлены массивом целых чисел row, где row[i] — это ID человека, сидящего на i-м месте. Пары пронумерованы по порядку: первая пара — (0, 1), вторая пара — (2, 3) и так далее, до последней пары — (2n - 2, 2n - 1).
Верните минимальное количество перестановок, чтобы каждая пара сидела рядом. Перестановка состоит из выбора любых двух человек, которые встают и меняются местами.
Пример:
👨💻 Алгоритм:
1⃣ Мы могли бы предположить без доказательства, что решение, при котором мы делаем людей на каждом диване счастливыми по порядку, является оптимальным. Это предположение сильнее, чем гипотеза о жадном подходе, но кажется разумным, поскольку при каждом ходе мы делаем хотя бы одну пару счастливой.
2⃣ При таком предположении, для какого-то дивана с несчастливыми людьми X и Y, мы либо заменяем Y на партнера X, либо заменяем X на партнера Y. Для каждой из двух возможностей мы можем попробовать оба варианта, используя подход с возвратом.
3⃣ Для каждого дивана с двумя возможностями (т.е. оба человека на диване несчастливы) мы попробуем первый вариант, найдем ответ как ans1, затем отменим наш ход и попробуем второй вариант, найдем связанный ответ как ans2, отменим наш ход и затем вернем наименьший ответ.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 765. Couples Holding Hands
Есть n пар, сидящих на 2n местах, расположенных в ряд, и они хотят держаться за руки.
Люди и места представлены массивом целых чисел row, где row[i] — это ID человека, сидящего на i-м месте. Пары пронумерованы по порядку: первая пара — (0, 1), вторая пара — (2, 3) и так далее, до последней пары — (2n - 2, 2n - 1).
Верните минимальное количество перестановок, чтобы каждая пара сидела рядом. Перестановка состоит из выбора любых двух человек, которые встают и меняются местами.
Пример:
Input: row = [0,2,1,3]
Output: 1
Explanation: We only need to swap the second (row[1]) and third (row[2]) person.
class Solution {
private $N;
private $pairs;
function minSwapsCouples($row) {
$this->N = count($row) / 2;
$this->pairs = array_fill(0, $this->N, [0, 0]);
for ($i = 0; $i < $this->N; ++$i) {
$this->pairs[$i][0] = intval($row[2 * $i] / 2);
$this->pairs[$i][1] = intval($row[2 * $i + 1] / 2);
}
return $this->solve(0);
}
function swap($a, $b, $c, $d) {
$t = $this->pairs[$a][$b];
$this->pairs[$a][$b] = $this->pairs[$c][$d];
$this->pairs[$c][$d] = $t;
}
function solve($i) {
if ($i == $this->N) return 0;
$x = $this->pairs[$i][0];
$y = $this->pairs[$i][1];
if ($x == $y) return $this->solve($i + 1);
$jx = $kx = $jy = $ky = 0;
for ($j = $i + 1; $j < $this->N; ++$j) {
for ($k = 0; $k <= 1; ++$k) {
if ($this->pairs[$j][$k] == $x) { $jx = $j; $kx = $k; }
if ($this->pairs[$j][$k] == $y) { $jy = $j; $ky = $k; }
}
}
$this->swap($i, 1, $jx, $kx);
$ans1 = 1 + $this->solve($i + 1);
$this->swap($i, 1, $jx, $kx);
$this->swap($i, 0, $jy, $ky);
$ans2 = 1 + $this->solve($i + 1);
$this->swap($i, 0, $jy, $ky);
return min($ans1, $ans2);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 715. Range Module
Модуль Range - это модуль, который отслеживает диапазоны чисел. Создайте структуру данных для отслеживания диапазонов, представленных в виде полуоткрытых интервалов, и запросов к ним. Полуоткрытый интервал [left, right) обозначает все вещественные числа x, где left <= x < right. Реализуйте класс RangeModule: RangeModule() Инициализирует объект структуры данных. void addRange(int left, int right) Добавляет полуоткрытый интервал [left, right), отслеживая каждое вещественное число в этом интервале. Добавление интервала, который частично перекрывает отслеживаемые в данный момент числа, должно добавить все числа в интервале [left, right), которые еще не отслеживаются. boolean queryRange(int left, int right) Возвращает true, если каждое действительное число в интервале [left, right) отслеживается в данный момент, и false в противном случае. void removeRange(int left, int right) Прекращает отслеживание каждого действительного числа, отслеживаемого в данный момент в полуоткрытом интервале [left, right).
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте класс RangeModule с пустым списком диапазонов.
2⃣ Для метода addRange(left, right) добавьте новый диапазон, объединяя его с существующими перекрывающимися диапазонами. Для метода queryRange(left, right) проверьте, полностью ли данный диапазон содержится в отслеживаемых диапазонах.
3⃣ Для метода removeRange(left, right) удалите указанный диапазон, разбивая существующие диапазоны на соответствующие части.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 715. Range Module
Модуль Range - это модуль, который отслеживает диапазоны чисел. Создайте структуру данных для отслеживания диапазонов, представленных в виде полуоткрытых интервалов, и запросов к ним. Полуоткрытый интервал [left, right) обозначает все вещественные числа x, где left <= x < right. Реализуйте класс RangeModule: RangeModule() Инициализирует объект структуры данных. void addRange(int left, int right) Добавляет полуоткрытый интервал [left, right), отслеживая каждое вещественное число в этом интервале. Добавление интервала, который частично перекрывает отслеживаемые в данный момент числа, должно добавить все числа в интервале [left, right), которые еще не отслеживаются. boolean queryRange(int left, int right) Возвращает true, если каждое действительное число в интервале [left, right) отслеживается в данный момент, и false в противном случае. void removeRange(int left, int right) Прекращает отслеживание каждого действительного числа, отслеживаемого в данный момент в полуоткрытом интервале [left, right).
Пример:
Input
["RangeModule", "addRange", "removeRange", "queryRange", "queryRange", "queryRange"]
[[], [10, 20], [14, 16], [10, 14], [13, 15], [16, 17]]
Output
[null, null, null, true, false, true]
class RangeModule {
private $ranges;
function __construct() {
$this->ranges = [];
}
function addRange($left, $right) {
$newRanges = [];
$i = 0;
while ($i < count($this->ranges) && $this->ranges[$i][1] < $left) {
$newRanges[] = $this->ranges[$i];
$i++;
}
while ($i < count($this->ranges) && $this->ranges[$i][0] <= $right) {
$left = min($left, $this->ranges[$i][0]);
$right = max($right, $this->ranges[$i][1]);
$i++;
}
$newRanges[] = [$left, $right];
while ($i < count($this->ranges)) {
$newRanges[] = $this->ranges[$i];
$i++;
}
$this->ranges = $newRanges;
}
function queryRange($left, $right) {
foreach ($this->ranges as $range) {
if ($range[0] <= $left && $right <= $range[1]) {
return true;
}
}
return false;
}
function removeRange($left, $right) {
$newRanges = [];
foreach ($this->ranges as $range) {
if ($range[0] < $left) {
$newRanges[] = [$range[0], min($range[1], $left)];
}
if ($right < $range[1]) {
$newRanges[] = [max($range[0], $right), $range[1]];
}
}
$this->ranges = $newRanges;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 774. Minimize Max Distance to Gas Station
Вам дан массив целых чисел stations, который представляет позиции автозаправочных станций на оси x. Вам также дано целое число k.
Вы должны добавить k новых автозаправочных станций. Вы можете добавлять станции в любое место на оси x, необязательно в целочисленную позицию.
Определим penalty() как максимальное расстояние между соседними автозаправочными станциями после добавления k новых станций.
Верните наименьшее возможное значение penalty(). Ответы, отличающиеся от фактического ответа не более чем на 10^-6, будут приняты.
Пример:
👨💻 Алгоритм:
1⃣ Пусть i-й интервал равен deltas[i] = stations[i+1] - stations[i]. Мы хотим найти dp[n+1][k] как рекурсию. Мы можем поставить x автозаправочных станций в интервал n+1 с наилучшим расстоянием deltas[n+1] / (x+1), затем оставшиеся интервалы можно решить с ответом dp[n][k-x]. Ответ — это минимум среди всех x.
2⃣ Из этой рекурсии мы можем разработать решение с использованием динамического программирования. Инициализируем двумерный массив dp, где dp[i][j] будет хранить минимальное возможное значение penalty при добавлении j автозаправочных станций на первые i интервалов.
3⃣ Заполняем dp таблицу начиная с базового случая, когда нет добавленных станций. Затем для каждого интервала и количества добавленных станций вычисляем минимальное значение penalty, используя вышеописанную рекурсию. Итоговый ответ будет находиться в dp[n][k], где n — количество интервалов, а k — количество добавляемых станций.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 774. Minimize Max Distance to Gas Station
Вам дан массив целых чисел stations, который представляет позиции автозаправочных станций на оси x. Вам также дано целое число k.
Вы должны добавить k новых автозаправочных станций. Вы можете добавлять станции в любое место на оси x, необязательно в целочисленную позицию.
Определим penalty() как максимальное расстояние между соседними автозаправочными станциями после добавления k новых станций.
Верните наименьшее возможное значение penalty(). Ответы, отличающиеся от фактического ответа не более чем на 10^-6, будут приняты.
Пример:
Input: stations = [1,2,3,4,5,6,7,8,9,10], k = 9
Output: 0.50000
class Solution {
function minmaxGasDist($stations, $K) {
$N = count($stations);
$deltas = array_fill(0, $N-1, 0);
for ($i = 0; $i < $N-1; ++$i)
$deltas[$i] = $stations[$i+1] - $stations[$i];
$dp = array_fill(0, $N-1, array_fill(0, $K+1, 0));
for ($i = 0; $i <= $K; ++$i)
$dp[0][$i] = $deltas[0] / ($i+1);
for ($p = 1; $p < $N-1; ++$p)
for ($k = 0; $k <= $K; ++$k) {
$bns = 999999999;
for ($x = 0; $x <= $k; ++$x)
$bns = min($bns, max($deltas[$p] / ($x+1), $dp[$p-1][$k-$x]));
$dp[$p][$k] = $bns;
}
return $dp[$N-2][$K];
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
#hard
Задача: 719. Find K-th Smallest Pair Distance
Расстояние между парой целых чисел a и b определяется как абсолютная разность между a и b. Учитывая целочисленный массив nums и целое число k, верните k-е наименьшее расстояние среди всех пар nums[i] и nums[j], где 0 <= i < j < nums.length.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте массив nums.
2⃣ Определите минимальное и максимальное возможные расстояния.
3⃣ Используйте бинарный поиск, чтобы найти k-е наименьшее расстояние, проверяя количество пар с расстоянием меньше или равно текущему среднему значению.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 719. Find K-th Smallest Pair Distance
Расстояние между парой целых чисел a и b определяется как абсолютная разность между a и b. Учитывая целочисленный массив nums и целое число k, верните k-е наименьшее расстояние среди всех пар nums[i] и nums[j], где 0 <= i < j < nums.length.
Пример:
Input: nums = [1,3,1], k = 1
Output: 0
function countPairs($nums, $mid) {
$count = 0;
$j = 0;
for ($i = 0; $i < count($nums); $i++) {
while ($j < count($nums) && $nums[$j] - $nums[$i] <= $mid) {
$j++;
}
$count += $j - $i - 1;
}
return $count;
}
function smallestDistancePair($nums, $k) {
sort($nums);
$left = 0;
$right = $nums[count($nums) - 1] - $nums[0];
while ($left < $right) {
$mid = (int)(($left + $right) / 2);
if (countPairs($nums, $mid) < $k) {
$left = $mid + 1;
} else {
$right = $mid;
}
}
return $left;
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 489. Robot Room Cleaner
Вы управляете роботом в комнате, представленной бинарной сеткой m x n, где 0 — стена, а 1 — пустая ячейка.
Робот начинает в неизвестном месте, гарантированно пустом. У вас нет доступа к сетке, но вы можете перемещать робота через предоставленный API Robot.
Роботу нужно очистить всю комнату (т.е. все пустые ячейки). Он может двигаться вперед, поворачивать налево или направо на 90 градусов.
Если робот наталкивается на стену, его датчик препятствия обнаруживает это, и он остается на текущей ячейке.
Разработайте алгоритм для очистки всей комнаты, используя следующие API:
Пример:
👨💻 Алгоритм:
1⃣ Пометьте текущую ячейку как посещенную и очистите её.
2⃣ Исследуйте четыре направления (вверх, вправо, вниз, влево) последовательно, двигаясь и очищая новые ячейки, если возможно.
3⃣ Если движение невозможно (стена или посещенная ячейка), поверните направо и попробуйте снова, возвращаясь назад, если необходимо.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 489. Robot Room Cleaner
Вы управляете роботом в комнате, представленной бинарной сеткой m x n, где 0 — стена, а 1 — пустая ячейка.
Робот начинает в неизвестном месте, гарантированно пустом. У вас нет доступа к сетке, но вы можете перемещать робота через предоставленный API Robot.
Роботу нужно очистить всю комнату (т.е. все пустые ячейки). Он может двигаться вперед, поворачивать налево или направо на 90 градусов.
Если робот наталкивается на стену, его датчик препятствия обнаруживает это, и он остается на текущей ячейке.
Разработайте алгоритм для очистки всей комнаты, используя следующие API:
interface Robot {
// возвращает true, если следующая ячейка открыта и робот перемещается в эту ячейку.
// возвращает false, если следующая ячейка является препятствием и робот остается на текущей ячейке.
boolean move();
// Робот останется на той же ячейке после вызова turnLeft/turnRight.
// Каждый поворот составляет 90 градусов.
void turnLeft();
void turnRight();
// Очистить текущую ячейку.
void clean();
}Пример:
Input: room = [[1,1,1,1,1,0,1,1],[1,1,1,1,1,0,1,1],[1,0,1,1,1,1,1,1],[0,0,0,1,0,0,0,0],[1,1,1,1,1,1,1,1]], row = 1, col = 3
Output: Robot cleaned all rooms.
Explanation: All grids in the room are marked by either 0 or 1.
0 means the cell is blocked, while 1 means the cell is accessible.
The robot initially starts at the position of row=1, col=3.
From the top left corner, its position is one row below and three columns right.
class Solution {
private $robot;
private $visited;
private $directions;
public function __construct() {
$this->visited = [];
$this->directions = [[-1, 0], [0, 1], [1, 0], [0, -1]];
}
private function goBack() {
$this->robot->turnRight();
$this->robot->turnRight();
$this->robot->move();
$this->robot->turnRight();
$this->robot->turnRight();
}
private function backtrack($row, $col, $d) {
$this->visited["$row,$col"] = true;
$this->robot->clean();
for ($i = 0; $i < 4; $i++) {
$newD = ($d + $i) % 4;
$newRow = $row + $this->directions[$newD][0];
$newCol = $col + $this->directions[$newD][1];
if (!isset($this->visited["$newRow,$newCol"]) && $this->robot->move()) {
$this->backtrack($newRow, $newCol, $newD);
$this->goBack();
}
$this->robot->turnRight();
}
}
public function cleanRoom($robot) {
$this->robot = $robot;
$this->backtrack(0, 0, 0);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 499. The Maze III
В лабиринте есть мячик с пустыми пространствами (0) и стенами (1). Мячик может катиться вверх, вниз, влево или вправо, пока не столкнется со стеной, затем выбрать новое направление. В лабиринте также есть отверстие, куда мячик упадет, если закатится в него.
Дан лабиринт размером m x n, позиция мяча ball и отверстия hole, где ball = [ballrow, ballcol] и hole = [holerow, holecol]. Верните строку instructions с кратчайшим путем мячика к отверстию. Если существует несколько вариантов, верните лексикографически минимальный. Если путь невозможен, верните "impossible". Ответ должен содержать 'u' (вверх), 'd' (вниз), 'l' (влево) и 'r' (вправо).
Расстояние — это количество пройденных пустых пространств от начальной позиции (исключительно) до конечной (включительно).
Вы можете предположить, что границы лабиринта — это стены. В примере ниже они не указаны.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и вспомогательные функции
Создайте функцию valid для проверки, находится ли координата (row, col) в пределах лабиринта и является ли она пустым пространством. Создайте функцию getNeighbors для получения списка соседей для данной позиции. Двигайтесь в каждом направлении (вверх, вниз, влево, вправо) до встречи со стеной.
2⃣ Запуск алгоритма Дейкстры
Инициализируйте очередь с начальной позицией мяча, где элементы с меньшим расстоянием имеют высокий приоритет, а при равных расстояниях выбирайте минимальную строку пути. Создайте структуру seen для отслеживания посещенных узлов.
3⃣ Поиск кратчайшего пути
Пока очередь не пуста, извлекайте узел с наименьшим расстоянием. Если узел посещен, пропустите его. Если это отверстие, верните текущий путь. Отметьте узел как посещенный, добавьте его соседей в очередь, обновив расстояние и путь. Если пути нет, верните "impossible".
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 499. The Maze III
В лабиринте есть мячик с пустыми пространствами (0) и стенами (1). Мячик может катиться вверх, вниз, влево или вправо, пока не столкнется со стеной, затем выбрать новое направление. В лабиринте также есть отверстие, куда мячик упадет, если закатится в него.
Дан лабиринт размером m x n, позиция мяча ball и отверстия hole, где ball = [ballrow, ballcol] и hole = [holerow, holecol]. Верните строку instructions с кратчайшим путем мячика к отверстию. Если существует несколько вариантов, верните лексикографически минимальный. Если путь невозможен, верните "impossible". Ответ должен содержать 'u' (вверх), 'd' (вниз), 'l' (влево) и 'r' (вправо).
Расстояние — это количество пройденных пустых пространств от начальной позиции (исключительно) до конечной (включительно).
Вы можете предположить, что границы лабиринта — это стены. В примере ниже они не указаны.
Пример:
Input: maze = [[0,0,0,0,0],[1,1,0,0,1],[0,0,0,0,0],[0,1,0,0,1],[0,1,0,0,0]], ball = [4,3], hole = [0,1]
Output: "lul"
Создайте функцию valid для проверки, находится ли координата (row, col) в пределах лабиринта и является ли она пустым пространством. Создайте функцию getNeighbors для получения списка соседей для данной позиции. Двигайтесь в каждом направлении (вверх, вниз, влево, вправо) до встречи со стеной.
Инициализируйте очередь с начальной позицией мяча, где элементы с меньшим расстоянием имеют высокий приоритет, а при равных расстояниях выбирайте минимальную строку пути. Создайте структуру seen для отслеживания посещенных узлов.
Пока очередь не пуста, извлекайте узел с наименьшим расстоянием. Если узел посещен, пропустите его. Если это отверстие, верните текущий путь. Отметьте узел как посещенный, добавьте его соседей в очередь, обновив расстояние и путь. Если пути нет, верните "impossible".
class State {
public $row, $col, $dist, $path;
public function __construct($r, $c, $d, $p) {
$this->row = $r; $this->col = $c; $this->dist = $d; $this->path = $p;
}
}
class MinHeap extends SplMinHeap {
protected function compare($a, $b) {
return $a->dist === $b->dist ? strcmp($a->path, $b->path) : $a->dist - $b->dist;
}
}
class Solution {
private $dirs = [[0, -1], [-1, 0], [0, 1], [1, 0]];
private $dirText = ["l", "u", "r", "d"];
function findShortestWay($maze, $ball, $hole) {
$m = count($maze); $n = count($maze[0]);
$heap = new MinHeap();
$seen = array_fill(0, $m, array_fill(0, $n, false));
$heap->insert(new State($ball[0], $ball[1], 0, ""));
while (!$heap->isEmpty()) {
$curr = $heap->extract();
if ($seen[$curr->row][$curr->col]) continue;
if ($curr->row == $hole[0] && $curr->col == $hole[1]) return $curr->path;
$seen[$curr->row][$curr->col] = true;
foreach ($this->dirs as $i => [$dy, $dx]) {
$r = $curr->row; $c = $curr->col; $dist = 0;
while ($r + $dy >= 0 && $r + $dy < $m && $c + $dx >= 0 && $c + $dx < $n && $maze[$r + $dy][$c + $dx] == 0) {
$r += $dy; $c += $dx; $dist++;
if ($r == $hole[0] && $c == $hole[1]) break;
}
$heap->insert(new State($r, $c, $curr->dist + $dist, $curr->path . $this->dirText[$i]));
}
}
return "impossible";
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 502. IPO
LeetCode планирует IPO и хочет увеличить капитал, выполняя проекты. У компании ограниченные ресурсы, поэтому она может завершить до k проектов. Помогите LeetCode максимизировать капитал после завершения этих проектов.
У вас есть n проектов с чистой прибылью profits[i] и минимальным капиталом capital[i] для начала.
Изначально у вас есть капитал w. Завершив проект, вы получаете его прибыль, которая добавляется к вашему капиталу.
Выберите до k проектов, чтобы максимально увеличить капитал, и верните его окончательное значение. Ответ гарантированно поместится в 32-битное целое число.
Пример:
👨💻 Алгоритм:
1⃣ Сортировка и инициализация
Отсортируйте проекты по возрастанию капитала. Создайте указатель ptr на первый недоступный проект в отсортированном массиве. Создайте приоритетную очередь для прибылей доступных проектов. Изначально очередь пуста.
2⃣ Выбор проектов
Выполните следующие действия k раз: добавьте в приоритетную очередь прибыли новых доступных проектов. Перемещайте указатель по отсортированному массиву, когда проекты становятся доступными. Если приоритетная очередь пуста, завершите алгоритм.
3⃣ Увеличение капитала
Максимальное значение в приоритетной очереди — это прибыль проекта, который будет запущен сейчас. Увеличьте капитал на это значение. Удалите его из очереди, так как он больше не может быть использован.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 502. IPO
LeetCode планирует IPO и хочет увеличить капитал, выполняя проекты. У компании ограниченные ресурсы, поэтому она может завершить до k проектов. Помогите LeetCode максимизировать капитал после завершения этих проектов.
У вас есть n проектов с чистой прибылью profits[i] и минимальным капиталом capital[i] для начала.
Изначально у вас есть капитал w. Завершив проект, вы получаете его прибыль, которая добавляется к вашему капиталу.
Выберите до k проектов, чтобы максимально увеличить капитал, и верните его окончательное значение. Ответ гарантированно поместится в 32-битное целое число.
Пример:
Input: k = 2, w = 0, profits = [1,2,3], capital = [0,1,1]
Output: 4
Explanation: Since your initial capital is 0, you can only start the project indexed 0.
After finishing it you will obtain profit 1 and your capital becomes 1.
With capital 1, you can either start the project indexed 1 or the project indexed 2.
Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital.
Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4.
Отсортируйте проекты по возрастанию капитала. Создайте указатель ptr на первый недоступный проект в отсортированном массиве. Создайте приоритетную очередь для прибылей доступных проектов. Изначально очередь пуста.
Выполните следующие действия k раз: добавьте в приоритетную очередь прибыли новых доступных проектов. Перемещайте указатель по отсортированному массиву, когда проекты становятся доступными. Если приоритетная очередь пуста, завершите алгоритм.
Максимальное значение в приоритетной очереди — это прибыль проекта, который будет запущен сейчас. Увеличьте капитал на это значение. Удалите его из очереди, так как он больше не может быть использован.
class State {
public $row, $col, $dist, $path;
public function __construct($r, $c, $d, $p) {
$this->row = $r; $this->col = $c; $this->dist = $d; $this->path = $p;
}
}
class MinHeap extends SplMinHeap {
protected function compare($value1, $value2) {
if ($value1->dist == $value2->dist) {
return strcmp($value1->path, $value2->path);
}
return $value1->dist - $value2->dist;
}
}
class Solution {
private $directions = [[0, -1], [-1, 0], [0, 1], [1, 0]];
private $textDirections = ["l", "u", "r", "d"];
private $m, $n;
function findShortestWay($maze, $ball, $hole) {
$this->m = count($maze); $this->n = count($maze[0]);
$heap = new MinHeap();
$seen = array_fill(0, $this->m, array_fill(0, $this->n, false));
$heap->insert(new State($ball[0], $ball[1], 0, ""));
while (!$heap->isEmpty()) {
$curr = $heap->extract();
if ($seen[$curr->row][$curr->col]) continue;
if ($curr->row == $hole[0] && $curr->col == $hole[1]) return $curr->path;
$seen[$curr->row][$curr->col] = true;
foreach ($this->dirs as $i => [$dy, $dx]) {
$r = $curr->row; $c = $curr->col; $dist = 0;
while ($r + $dy >= 0 && $r + $dy < $this->m && $c + $dx >= 0 && $c + $dx < $this->n && $maze[$r + $dy][$c + $dx] == 0) {
$r += $dy; $c += $dx; $dist++;
if ($r == $hole[0] && $c == $hole[1]) break;
}
$heap->insert(new State($r, $c, $curr->dist + $dist, $curr->path . $this->dirText[$i]));
}
}
return "impossible";
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 726. Number of Atoms
Если задана строковая формула, представляющая химическую формулу, верните количество атомов. Атомный элемент всегда начинается с прописного символа, затем ноль или более строчных букв, представляющих его название. Если количество больше 1, за ним может следовать одна или более цифр, представляющих количество элементов. Например, "H2O" и "H2O2" возможны, а "H1O2" невозможен. Две формулы объединяются вместе, чтобы получить другую формулу. Например, "H2O2He3Mg4" также является формулой.
Формула, заключенная в круглые скобки, и счет (по желанию) также являются формулами. Например, "(H2O2)" и "(H2O2)3" являются формулами.
Возвращает количество всех элементов в виде строки в следующем виде: первое имя (в отсортированном порядке), затем его количество (если это количество больше 1), затем второе имя (в отсортированном порядке), затем его количество (если это количество больше 1) и т. д. Тестовые примеры генерируются таким образом, чтобы все значения в выводе помещались в 32-битное целое число.
Пример:
👨💻 Алгоритм:
1⃣ Используйте стек для отслеживания текущего уровня скобок.
2⃣ Пройдите по строке формулы, анализируя каждый символ: Если символ - это открывающая скобка '(', создайте новый словарь для хранения атомов внутри скобок. Если символ - это закрывающая скобка ')', извлеките словарь из стека и умножьте количества атомов на последующее число, если оно присутствует. Если символ - это атом (начинается с заглавной буквы), извлеките имя атома и его количество, и добавьте его в текущий словарь.
3⃣ После завершения обработки строки, объедините все словари из стека и отсортируйте результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 726. Number of Atoms
Если задана строковая формула, представляющая химическую формулу, верните количество атомов. Атомный элемент всегда начинается с прописного символа, затем ноль или более строчных букв, представляющих его название. Если количество больше 1, за ним может следовать одна или более цифр, представляющих количество элементов. Например, "H2O" и "H2O2" возможны, а "H1O2" невозможен. Две формулы объединяются вместе, чтобы получить другую формулу. Например, "H2O2He3Mg4" также является формулой.
Формула, заключенная в круглые скобки, и счет (по желанию) также являются формулами. Например, "(H2O2)" и "(H2O2)3" являются формулами.
Возвращает количество всех элементов в виде строки в следующем виде: первое имя (в отсортированном порядке), затем его количество (если это количество больше 1), затем второе имя (в отсортированном порядке), затем его количество (если это количество больше 1) и т. д. Тестовые примеры генерируются таким образом, чтобы все значения в выводе помещались в 32-битное целое число.
Пример:
Input: formula = "H2O"
Output: "H2O"
function countOfAtoms($formula) {
$stack = [array()];
$n = strlen($formula);
$i = 0;
while ($i < $n) {
if ($formula[$i] == '(') {
array_push($stack, array());
$i++;
} else if ($formula[$i] == ')') {
$top = array_pop($stack);
$i++;
$i_start = $i;
while ($i < $n && is_numeric($formula[$i])) {
$i++;
}
$multiplicity = $i > $i_start ? intval(substr($formula, $i_start, $i - $i_start)) : 1;
foreach ($top as $name => $count) {
$stack[count($stack) - 1][$name] = ($stack[count($stack) - 1][$name] ?? 0) + $count * $multiplicity;
}
} else {
$i_start = $i;
$i++;
while ($i < $n && ctype_lower($formula[$i])) {
$i++;
}
$name = substr($formula, $i_start, $i - $i_start);
$i_start = $i;
while ($i < $n && is_numeric($formula[$i])) {
$i++;
}
$multiplicity = $i > $i_start ? intval(substr($formula, $i_start, $i - $i_start)) : 1;
$stack[count($stack) - 1][$name] = ($stack[count($stack) - 1][$name] ?? 0) + $multiplicity;
}
}
$countMap = $stack[0];
ksort($countMap);
$result = '';
foreach ($countMap as $name => $count) {
$result .= $name;
if ($count > 1) {
$result .= $count;
}
}
return $result;
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 727. Minimum Window Subsequence
Если в строках s1 и s2 нет такого окна, которое покрывало бы все символы в s2, верните пустую строку "". Если таких окон минимальной длины несколько, возвращается окно с самым левым начальным индексом.
Пример:
👨💻 Алгоритм:
1⃣ Используйте два указателя для определения текущего окна.
2⃣ Поддерживайте счетчики для символов в текущем окне и требуемых символов из s2.
3⃣ Перемещайте правый указатель, чтобы найти подходящее окно, и левый указатель, чтобы минимизировать его.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 727. Minimum Window Subsequence
Если в строках s1 и s2 нет такого окна, которое покрывало бы все символы в s2, верните пустую строку "". Если таких окон минимальной длины несколько, возвращается окно с самым левым начальным индексом.
Пример:
Input: s1 = "abcdebdde", s2 = "bde"
Output: "bcde"
function minWindow($s1, $s2) {
if (!$s1 || !$s2) {
return "";
}
$dictT = array_count_values(str_split($s2));
$required = count($dictT);
$l = 0;
$r = 0;
$formed = 0;
$windowCounts = [];
$ans = [PHP_INT_MAX, 0, 0];
while ($r < strlen($s1)) {
$char = $s1[$r];
$windowCounts[$char] = ($windowCounts[$char] ?? 0) + 1;
if (isset($dictT[$char]) && $windowCounts[$char] == $dictT[$char]) {
$formed++;
}
while ($l <= $r && $formed == $required) {
$char = $s1[$l];
if ($r - $l + 1 < $ans[0]) {
$ans = [$r - $l + 1, $l, $r];
}
$windowCounts[$char]--;
if (isset($dictT[$char]) && $windowCounts[$char] < $dictT[$char]) {
$formed--;
}
$l++;
}
$r++;
}
return $ans[0] == PHP_INT_MAX ? "" : substr($s1, $ans[1], $ans[0]);
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 728. Self Dividing Numbers
Например, 128 является саморазделяющимся числом, потому что 128 % 1 == 0, 128 % 2 == 0 и 128 % 8 == 0. Саморазделяющееся число не может содержать цифру ноль. Если даны два целых числа left и right, верните список всех саморазделяющихся чисел в диапазоне [left, right].
Пример:
👨💻 Алгоритм:
1⃣ Переберите все числа в диапазоне от left до right.
2⃣ Для каждого числа проверьте, является ли оно саморазделяющимся: Разделите число на его цифры. Убедитесь, что ни одна цифра не равна нулю и число делится на каждую из своих цифр без остатка.
3⃣ Добавьте саморазделяющиеся числа в результативный список и верните его.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 728. Self Dividing Numbers
Например, 128 является саморазделяющимся числом, потому что 128 % 1 == 0, 128 % 2 == 0 и 128 % 8 == 0. Саморазделяющееся число не может содержать цифру ноль. Если даны два целых числа left и right, верните список всех саморазделяющихся чисел в диапазоне [left, right].
Пример:
Input: left = 1, right = 22
Output: [1,2,3,4,5,6,7,8,9,11,12,15,22]
function selfDividingNumbers($left, $right) {
$result = [];
for ($num = $left; $num <= $right; $num++) {
if (isSelfDividing($num)) {
$result[] = $num;
}
}
return $result;
}
function isSelfDividing($num) {
$n = $num;
while ($n > 0) {
$digit = $n % 10;
if ($digit == 0 || $num % $digit != 0) {
return false;
}
$n = (int)($n / 10);
}
return true;
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 730. Count Different Palindromic Subsequences
Поскольку ответ может быть очень большим, верните его по модулю 109 + 7. Подпоследовательность строки получается путем удаления из нее нуля или более символов. Последовательность является палиндромной, если она равна последовательности, обращенной назад. Две последовательности a1, a2, ... и b1, b2, ... различны, если существует некоторое i, для которого ai != bi.
Пример:
👨💻 Алгоритм:
1⃣ Используйте динамическое программирование для подсчета количества палиндромных подпоследовательностей.
2⃣ Введите двумерный массив dp, где dp[i][j] представляет количество палиндромных подпоследовательностей в подстроке от i до j.
3⃣ Итерируйте по длине подстрок от 1 до длины строки и обновляйте значения в dp на основе состояния предыдущих подстрок.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 730. Count Different Palindromic Subsequences
Поскольку ответ может быть очень большим, верните его по модулю 109 + 7. Подпоследовательность строки получается путем удаления из нее нуля или более символов. Последовательность является палиндромной, если она равна последовательности, обращенной назад. Две последовательности a1, a2, ... и b1, b2, ... различны, если существует некоторое i, для которого ai != bi.
Пример:
Input: s = "bccb"
Output: 6
function countPalindromicSubsequences($s) {
$MOD = 1000000007;
$n = strlen($s);
$dp = array_fill(0, $n, array_fill(0, $n, 0));
for ($i = 0; $i < $n; $i++) {
$dp[$i][$i] = 1;
}
for ($length = 2; $length <= $n; $length++) {
for ($i = 0; $i <= $n - $length; $i++) {
$j = $i + $length - 1;
if ($s[$i] == $s[$j]) {
$l = $i + 1;
$r = $j - 1;
while ($l <= $r && $s[$l] != $s[$i]) $l++;
while ($l <= $r && $s[$r] != $s[$j]) $r--;
if ($l > $r) {
$dp[$i][$j] = $dp[$i + 1][$j - 1] * 2 + 2;
} else if ($l == $r) {
$dp[$i][$j] = $dp[$i + 1][$j - 1] * 2 + 1;
} else {
$dp[$i][$j] = $dp[$i + 1][$j - 1] * 2 - $dp[$l + 1][$r - 1];
}
} else {
$dp[$i][$j] = $dp[$i + 1][$j] + $dp[$i][$j - 1] - $dp[$i + 1][$j - 1];
}
$dp[$i][$j] = ($dp[$i][$j] + $MOD) % $MOD;
}
}
return $dp[0][$n - 1];
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 732. My Calendar III
k-бронирование происходит, когда k событий имеют некоторое непустое пересечение (т.е, дано некоторое время, общее для всех k событий). Даны некоторые события [startTime, endTime), после каждого данного события верните целое число k, представляющее максимальное k-бронирование между всеми предыдущими событиями. Реализация класса MyCalendarThree: MyCalendarThree() Инициализирует объект. int book(int startTime, int endTime) Возвращает целое число k, представляющее наибольшее целое число, при котором в календаре существует k-бронирование.
Пример:
👨💻 Алгоритм:
1⃣ Создайте два словаря для хранения изменений времени бронирования: один для начала событий, другой для конца событий.
2⃣ Для каждого нового события обновите словари начала и конца событий.
3⃣ Поддерживайте текущее количество активных бронирований и обновляйте максимальное количество активных бронирований по мере добавления новых событий.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 732. My Calendar III
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]
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;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 736. Parse Lisp Expression
Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.
Пример:
👨💻 Алгоритм:
1⃣ Определите функцию для оценки выражений.
2⃣ Используйте рекурсивный подход для обработки различных типов выражений (let, add, mult, и переменных).
3⃣ Используйте словарь для отслеживания значений переменных с учетом области видимости.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 736. Parse Lisp Expression
Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.
Пример:
Input: expression = "(let x 2 (mult x (let x 3 y 4 (add x y))))"
Output: 14
class Solution {
public function evaluate($expression) {
return $this->evaluateExpression($expression, []);
}
private function evaluateExpression($expression, $env) {
if ($expression[0] !== '(') {
if (is_numeric($expression) || $expression[0] === '-') {
return intval($expression);
}
return $env[$expression] ?? 0;
}
$tokens = $this->tokenize($expression);
if ($tokens[0] === "let") {
for ($i = 1; $i < count($tokens) - 2; $i += 2) {
$env[$tokens[$i]] = $this->evaluateExpression($tokens[$i + 1], $env);
}
return $this->evaluateExpression($tokens[count($tokens) - 1], $env);
} elseif ($tokens[0] === "add") {
return $this->evaluateExpression($tokens[1], $env) + $this->evaluateExpression($tokens[2], $env);
} elseif ($tokens[0] === "mult") {
return $this->evaluateExpression($tokens[1], $env) * $this->evaluateExpression($tokens[2], $env);
}
return 0;
}
private function tokenize($expression) {
$tokens = [];
$token = '';
$parens = 0;
for ($i = 0; $i < strlen($expression); $i++) {
$c = $expression[$i];
if ($c === '(') {
$parens++;
if ($parens === 1) continue;
} elseif ($c === ')') {
$parens--;
if ($parens === 0) {
$tokens = array_merge($tokens, $this->tokenize($token));
$token = '';
continue;
}
} elseif ($c === ' ' && $parens === 1) {
if ($token !== '') {
$tokens[] = $token;
$token = '';
}
continue;
}
$token .= $c;
}
if ($token !== '') {
$tokens[] = $token;
}
return $tokens;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 741. Cherry Pickup
Вам дана сетка n x n, представляющая поле вишен. Каждая клетка - одно из трех возможных целых чисел. 0 означает, что клетка пуста, и вы можете пройти через нее, 1 означает, что клетка содержит вишню, которую вы можете сорвать и пройти через нее, или -1 означает, что клетка содержит шип, который преграждает вам путь. Верните максимальное количество вишен, которое вы можете собрать, следуя следующим правилам: Начиная с позиции (0, 0) и достигая (n - 1, n - 1) путем перемещения вправо или вниз через допустимые клетки пути (клетки со значением 0 или 1).
После достижения (n - 1, n - 1) вернитесь в (0, 0), двигаясь влево или вверх по клеткам с действительными путями. Проходя через клетку пути, содержащую вишню, вы поднимаете ее, и клетка становится пустой клеткой 0. Если между (0, 0) и (n - 1, n - 1) нет действительного пути, то вишни собрать нельзя.
Пример:
👨💻 Алгоритм:
1⃣ Используйте динамическое программирование для подсчета максимального количества вишен, которые можно собрать при движении от (0, 0) до (n - 1, n - 1).
2⃣ Примените еще один проход с использованием динамического программирования для движения обратно от (n - 1, n - 1) до (0, 0), чтобы учитывать вишни, собранные на обратном пути.
3⃣ Объедините результаты двух проходов, чтобы найти максимальное количество вишен, которые можно собрать.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 741. Cherry Pickup
Вам дана сетка n x n, представляющая поле вишен. Каждая клетка - одно из трех возможных целых чисел. 0 означает, что клетка пуста, и вы можете пройти через нее, 1 означает, что клетка содержит вишню, которую вы можете сорвать и пройти через нее, или -1 означает, что клетка содержит шип, который преграждает вам путь. Верните максимальное количество вишен, которое вы можете собрать, следуя следующим правилам: Начиная с позиции (0, 0) и достигая (n - 1, n - 1) путем перемещения вправо или вниз через допустимые клетки пути (клетки со значением 0 или 1).
После достижения (n - 1, n - 1) вернитесь в (0, 0), двигаясь влево или вверх по клеткам с действительными путями. Проходя через клетку пути, содержащую вишню, вы поднимаете ее, и клетка становится пустой клеткой 0. Если между (0, 0) и (n - 1, n - 1) нет действительного пути, то вишни собрать нельзя.
Пример:
Input: grid = [[0,1,-1],[1,0,-1],[1,1,1]]
Output: 5
function cherryPickup($grid) {
$n = count($grid);
$dp = array_fill(0, $n, array_fill(0, $n, array_fill(0, 2 * $n - 1, -INF)));
$dp[0][0][0] = $grid[0][0];
for ($k = 1; $k < 2 * $n - 1; $k++) {
for ($i1 = max(0, $k - $n + 1); $i1 <= min($n - 1, $k); $i1++) {
for ($i2 = max(0, $k - $n + 1); $i2 <= min($n - 1, $k); $i2++) {
$j1 = $k - $i1;
$j2 = $k - $i2;
if ($j1 < $n && $j2 < $n && $grid[$i1][$j1] != -1 && $grid[$i2][$j2] != -1) {
$maxCherries = -INF;
if ($i1 > 0 && $i2 > 0) $maxCherries = max($maxCherries, $dp[$i1 - 1][$i2 - 1][$k - 1]);
if ($i1 > 0) $maxCherries = max($maxCherries, $dp[$i1 - 1][$i2][$k - 1]);
if ($i2 > 0) $maxCherries = max($maxCherries, $dp[$i1][$i2 - 1][$k - 1]);
$maxCherries = max($maxCherries, $dp[$i1][$i2][$k - 1]);
if ($maxCherries != -INF) {
$dp[$i1][$i2][$k] = $maxCherries + $grid[$i1][$j1];
if ($i1 != $i2) $dp[$i1][$i2][$k] += $grid[$i2][$j2];
}
}
}
}
}
return max(0, $dp[$n - 1][$n - 1][2 * $n - 1]);
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 745. Prefix and Suffix Search
Создайте специальный словарь, в котором поиск слов осуществляется по префиксу и суффиксу. Реализуйте класс WordFilter: WordFilter(string[] words) Инициализирует объект со словами в словаре. f(string pref, string suff) Возвращает индекс слова в словаре, которое имеет префикс pref и суффикс suff. Если существует более одного допустимого индекса, возвращается наибольший из них. Если в словаре нет такого слова, возвращается -1.
Пример:
👨💻 Алгоритм:
1⃣ Сохраните слова и их индексы в словаре.
2⃣ Создайте объединенные ключи, состоящие из префиксов и суффиксов для всех возможных комбинаций.
3⃣ Реализуйте функцию поиска, которая ищет наибольший индекс слова по префиксу и суффиксу.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 745. Prefix and Suffix Search
Создайте специальный словарь, в котором поиск слов осуществляется по префиксу и суффиксу. Реализуйте класс WordFilter: WordFilter(string[] words) Инициализирует объект со словами в словаре. f(string pref, string suff) Возвращает индекс слова в словаре, которое имеет префикс pref и суффикс suff. Если существует более одного допустимого индекса, возвращается наибольший из них. Если в словаре нет такого слова, возвращается -1.
Пример:
Input: letters = ["c","f","j"], target = "a"
Output: "c"
class WordFilter {
private $prefixSuffixMap = [];
function __construct($words) {
foreach ($words as $index => $word) {
$length = strlen($word);
for ($prefixLength = 1; $prefixLength <= $length; $prefixLength++) {
for ($suffixLength = 1; $suffixLength <= $length; $suffixLength++) {
$prefix = substr($word, 0, $prefixLength);
$suffix = substr($word, $length - $suffixLength);
$key = $prefix . '#' . $suffix;
$this->prefixSuffixMap[$key] = $index;
}
}
}
}
function f($pref, $suff) {
$key = $pref . '#' . $suff;
return array_key_exists($key, $this->prefixSuffixMap) ? $this->prefixSuffixMap[$key] : -1;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 928. Minimize Malware Spread II
Вам дана сеть из n узлов, представленная в виде графа с матрицей смежности n x n, где i-й узел непосредственно связан с j-м узлом, если graph[i][j] == 1. Некоторые узлы изначально заражены вредоносным ПО. Если два узла соединены напрямую и хотя бы один из них заражен вредоносным ПО, то оба узла будут заражены вредоносным ПО. Такое распространение вредоносного ПО будет продолжаться до тех пор, пока больше не останется ни одного узла, зараженного таким образом. Предположим, что M(initial) - это конечное число узлов, зараженных вредоносным ПО, во всей сети после прекращения распространения вредоносного ПО. Мы удалим ровно один узел из initial, полностью удалив его и все связи от этого узла к любому другому узлу. Верните узел, который, если его удалить, минимизирует M(initial). Если для минимизации M(initial) можно удалить несколько узлов, верните такой узел с наименьшим индексом.
Пример:
👨💻 Алгоритм:
1⃣ Определить компоненты связности в графе. Для каждой компоненты связности определить количество зараженных узлов и общее количество узлов.
2⃣ Для каждого узла в initial удалить его и пересчитать количество зараженных узлов.
3⃣ Найти узел, удаление которого минимизирует количество зараженных узлов. Если несколько узлов минимизируют количество зараженных узлов одинаково, выбрать узел с наименьшим индексом.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 928. Minimize Malware Spread II
Вам дана сеть из n узлов, представленная в виде графа с матрицей смежности n x n, где i-й узел непосредственно связан с j-м узлом, если graph[i][j] == 1. Некоторые узлы изначально заражены вредоносным ПО. Если два узла соединены напрямую и хотя бы один из них заражен вредоносным ПО, то оба узла будут заражены вредоносным ПО. Такое распространение вредоносного ПО будет продолжаться до тех пор, пока больше не останется ни одного узла, зараженного таким образом. Предположим, что M(initial) - это конечное число узлов, зараженных вредоносным ПО, во всей сети после прекращения распространения вредоносного ПО. Мы удалим ровно один узел из initial, полностью удалив его и все связи от этого узла к любому другому узлу. Верните узел, который, если его удалить, минимизирует M(initial). Если для минимизации M(initial) можно удалить несколько узлов, верните такой узел с наименьшим индексом.
Пример:
Input: graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]
Output: 0
function minMalwareSpread($graph, $initial) {
$n = count($graph);
function dfs($node, &$visited, &$component, $graph, $n) {
$stack = [$node];
while (!empty($stack)) {
$u = array_pop($stack);
$component[] = $u;
for ($v = 0; $v < $n; $v++) {
if ($graph[$u][$v] === 1 && !isset($visited[$v])) {
$visited[$v] = true;
$stack[] = $v;
}
}
}
}
$components = [];
$visited = [];
for ($i = 0; $i < $n; $i++) {
if (!isset($visited[$i])) {
$component = [];
$visited[$i] = true;
dfs($i, $visited, $component, $graph, $n);
$components[] = $component;
}
}
$infectedInComponent = array_fill(0, count($components), 0);
$nodeToComponent = [];
foreach ($components as $idx => $component) {
foreach ($component as $node) {
$nodeToComponent[$node] = $idx;
}
}
foreach ($initial as $node) {
$componentIdx = $nodeToComponent[$node];
$infectedInComponent[$componentIdx]++;
}
sort($initial);
$minInfected = PHP_INT_MAX;
$resultNode = $initial[0];
foreach ($initial as $node) {
$componentIdx = $nodeToComponent[$node];
if ($infectedInComponent[$componentIdx] === 1) {
$componentSize = count($components[$componentIdx]);
if ($componentSize < $minInfected || ($componentSize === $minInfected && $node < $resultNode)) {
$minInfected = $componentSize;
$resultNode = $node;
}
}
}
return $resultNode;
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 757. Set Intersection Size At Least Two
Вам дан двумерный целочисленный массив intervals, в котором intervals[i] = [starti, endi] представляет все целые числа от starti до endi включительно. Содержащее множество - это массив nums, в котором каждый интервал из intervals содержит не менее двух целых чисел в nums. Например, если intervals = [[1,3], [3,7], [8,9]], то [1,2,4,7,8,9] и [2,3,4,8,9] - содержащие множества. Верните минимально возможный размер содержащего множества.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте интервалы по их конечным точкам.
2⃣ Инициализируйте пустое множество для хранения чисел.
3⃣ Пройдите по каждому интервалу, добавляя необходимые числа в множество так, чтобы каждый интервал содержал не менее двух чисел из этого множества.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 757. Set Intersection Size At Least Two
Вам дан двумерный целочисленный массив intervals, в котором intervals[i] = [starti, endi] представляет все целые числа от starti до endi включительно. Содержащее множество - это массив nums, в котором каждый интервал из intervals содержит не менее двух целых чисел в nums. Например, если intervals = [[1,3], [3,7], [8,9]], то [1,2,4,7,8,9] и [2,3,4,8,9] - содержащие множества. Верните минимально возможный размер содержащего множества.
Пример:
Input: intervals = [[1,3],[3,7],[8,9]]
Output: 5
function minSetSize($intervals) {
usort($intervals, function($a, $b) {
return $a[1] - $b[1];
});
$nums = [];
foreach ($intervals as $interval) {
$start = $interval[0];
$end = $interval[1];
if (empty($nums) || end($nums) < $start) {
$nums[] = $end - 1;
$nums[] = $end;
} elseif (end($nums) == $end - 1) {
$nums[] = $end;
}
}
return count($nums);
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 827. Making A Large Island
Вам дан n x n бинарный матрица grid. Вам разрешено изменить не более одного 0 на 1.
Верните размер самого большого острова в grid после выполнения этой операции.
Остров — это группа 1, соединенных в 4 направлениях.
Пример:
👨💻 Алгоритм:
1⃣ Пройдите по матрице и пометьте каждую группу, используя уникальный индекс, и запомните её размер.
2⃣ Для каждого 0 в матрице проверьте соседние группы и вычислите потенциальный размер острова, если изменить этот 0 на 1.
3⃣ Возвращайте максимальный размер острова, учитывая как уже существующие острова, так и потенциальные, образованные после изменения 0 на 1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 827. Making A Large Island
Вам дан n x n бинарный матрица grid. Вам разрешено изменить не более одного 0 на 1.
Верните размер самого большого острова в grid после выполнения этой операции.
Остров — это группа 1, соединенных в 4 направлениях.
Пример:
Input: grid = [[1,1],[1,0]]
Output: 4
Explanation: Change the 0 to 1 and make the island bigger, only one island with area = 4.
class Solution {
private $dr = [-1, 0, 1, 0];
private $dc = [0, -1, 0, 1];
private $grid;
private $N;
function largestIsland($grid) {
$this->grid = $grid;
$this->N = count($grid);
$index = 2;
$area = array_fill(0, $this->N * $this->N + 2, 0);
for ($r = 0; $r < $this->N; ++$r) {
for ($c = 0; $c < $this->N; ++$c) {
if ($grid[$r][$c] == 1) {
$area[$index] = $this->dfs($r, $c, $index);
++$index;
}
}
}
$ans = max($area);
for ($r = 0; $r < $this->N; ++$r) {
for ($c = 0; $c < $this->N; ++$c) {
if ($grid[$r][$c] == 0) {
$seen = [];
foreach ($this->neighbors($r, $c) as $move) {
if ($grid[$move[0]][$move[1]] > 1) {
$seen[$grid[$move[0]][$move[1]]] = true;
}
}
$bns = 1;
foreach (array_keys($seen) as $i) {
$bns += $area[$i];
}
$ans = max($ans, $bns);
}
}
}
return $ans;
}
function dfs($r, $c, $index) {
$ans = 1;
$this->grid[$r][$c] = $index;
foreach ($this->neighbors($r, $c) as $move) {
if ($this->grid[$move[0]][$move[1]] == 1) {
$this->grid[$move[0]][$move[1]] = $index;
$ans += $this->dfs($move[0], $move[1], $index);
}
}
return $ans;
}
function neighbors($r, $c) {
$ans = [];
for ($k = 0; $k < 4; ++$k) {
$nr = $r + $this->dr[$k];
$nc = $c + $this->dc[$k];
if ($nr >= 0 && $nr < $this->N && $nc >= 0 && $nc < $this->N) {
$ans[] = [$nr, $nc];
}
}
return $ans;
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM