Задача: 625. Minimum Factorization
Сложность: medium
Если задано целое положительное число num, верните наименьшее целое положительное число x, умножение каждого разряда которого равно num. Если ответа нет или ответ не помещается в 32-битное знаковое целое число, возвращается 0.
Пример:
👨💻 Алгоритм:
1⃣ Если num равно 1, верните 1. Инициализируйте массив для хранения множителей.
2⃣ Разделите num на множители от 9 до 2, пока num больше 1. Если в процессе остаются множители больше 9, верните 0.
3⃣ Постройте результат, собирая найденные множители в обратном порядке. Если результат больше 32-битного целого числа, верните 0.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Если задано целое положительное число num, верните наименьшее целое положительное число x, умножение каждого разряда которого равно num. Если ответа нет или ответ не помещается в 32-битное знаковое целое число, возвращается 0.
Пример:
Input: num = 48
Output: 68
public class Solution {
public int SmallestFactorization(int num) {
if (num == 1) return 1;
List<int> factors = new List<int>();
for (int i = 9; i >= 2; i--) {
while (num % i == 0) {
factors.Add(i);
num /= i;
}
}
if (num > 1) return 0;
long result = 0;
for (int i = factors.Count - 1; i >= 0; i--) {
result = result * 10 + factors[i];
if (result > int.MaxValue) return 0;
}
return (int) result;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 568. Maximum Vacation Days
Сложность: hard
LeetCode хочет предоставить одному из своих лучших сотрудников возможность путешествовать по n городам для сбора задач по алгоритмам. Однако, как говорится, "делу время, потехе час". Вы можете брать отпуска в некоторых конкретных городах и неделях. Ваша задача — спланировать поездку, чтобы максимально увеличить количество дней отпуска, которые вы сможете взять, соблюдая при этом определенные правила и ограничения.
Правила и ограничения:
Вы можете путешествовать только между n городами, обозначенными индексами от 0 до n-1. Изначально вы находитесь в городе с индексом 0 в понедельник.
Города связаны рейсами. Рейсы представлены матрицей n x n, называемой flights, представляющей статус авиалинии от города i до города j. Если рейса из города i в город j нет, flights[i][j] == 0; иначе flights[i][j] == 1. Также для всех i выполняется flights[i][i] == 0.
У вас есть k недель (каждая неделя состоит из семи дней) для путешествий. Вы можете летать не более одного раза в день и можете летать только утром каждого понедельника. Время полета настолько короткое, что его влияние не учитывается.
Для каждого города у вас есть ограниченные дни отпуска в разные недели, заданные матрицей n x k, называемой days. Значение days[i][j] представляет максимальное количество дней отпуска, которые вы можете взять в городе i на неделе j.
Даны две матрицы flights и days, верните максимальное количество дней отпуска, которые вы можете взять в течение k недель.
Пример:
👨💻 Алгоритм:
1⃣ Использовать функцию dfs (поиск в глубину), которая возвращает количество отпускных дней, которые можно взять, начиная с текущего города cur_city и текущей недели weekno. В каждом вызове функции проходить по всем городам и находить все города, которые связаны с текущим городом. Такой город обозначен 1 в соответствующей позиции flights[cur_city][i].
2⃣ Для текущего города можно либо остаться в нем, либо поехать в связанный город. Обозначим город, в который меняется расположение, как j. После смены города нужно найти количество отпускных дней, которые можно взять, начиная с нового города и с новой недели. Это количество отпускных дней можно представить как: days[j][weekno] + dfs(flights, days, j, weekno + 1).
3⃣ Для текущего города необходимо найти максимальное количество отпускных дней, выбирая различные города в качестве следующего местоположения. Из всех вариантов отпускных дней выбираем максимальное значение, которое и будет возвращено для каждого вызова функции dfs.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
LeetCode хочет предоставить одному из своих лучших сотрудников возможность путешествовать по n городам для сбора задач по алгоритмам. Однако, как говорится, "делу время, потехе час". Вы можете брать отпуска в некоторых конкретных городах и неделях. Ваша задача — спланировать поездку, чтобы максимально увеличить количество дней отпуска, которые вы сможете взять, соблюдая при этом определенные правила и ограничения.
Правила и ограничения:
Вы можете путешествовать только между n городами, обозначенными индексами от 0 до n-1. Изначально вы находитесь в городе с индексом 0 в понедельник.
Города связаны рейсами. Рейсы представлены матрицей n x n, называемой flights, представляющей статус авиалинии от города i до города j. Если рейса из города i в город j нет, flights[i][j] == 0; иначе flights[i][j] == 1. Также для всех i выполняется flights[i][i] == 0.
У вас есть k недель (каждая неделя состоит из семи дней) для путешествий. Вы можете летать не более одного раза в день и можете летать только утром каждого понедельника. Время полета настолько короткое, что его влияние не учитывается.
Для каждого города у вас есть ограниченные дни отпуска в разные недели, заданные матрицей n x k, называемой days. Значение days[i][j] представляет максимальное количество дней отпуска, которые вы можете взять в городе i на неделе j.
Даны две матрицы flights и days, верните максимальное количество дней отпуска, которые вы можете взять в течение k недель.
Пример:
Input: flights = [[0,1,1],[1,0,1],[1,1,0]], days = [[1,3,1],[6,0,3],[3,3,3]]
Output: 12
Explanation:
One of the best strategies is:
1st week : fly from city 0 to city 1 on Monday, and play 6 days and work 1 day.
(Although you start at city 0, we could also fly to and start at other cities since it is Monday.)
2nd week : fly from city 1 to city 2 on Monday, and play 3 days and work 4 days.
3rd week : stay at city 2, and play 3 days and work 4 days.
Ans = 6 + 3 + 3 = 12.
public class Solution {
public int MaxVacationDays(int[][] flights, int[][] days) {
int n = flights.Length, k = days[0].Length;
int[][] memo = new int[n][];
for (int i = 0; i < n; i++) {
memo[i] = new int[k];
Array.Fill(memo[i], -1);
}
return Dfs(flights, days, memo, 0, 0);
}
private int Dfs(int[][] flights, int[][] days, int[][] memo, int curCity, int weekNo) {
int n = flights.Length, k = days[0].Length;
if (weekNo == k) return 0;
if (memo[curCity][weekNo] != -1) return memo[curCity][weekNo];
int maxVac = 0;
for (int nextCity = 0; nextCity < n; nextCity++) {
if (curCity == nextCity || flights[curCity][nextCity] == 1) {
maxVac = Math.Max(maxVac, days[nextCity][weekNo] + Dfs(flights, days, memo, nextCity, weekNo + 1));
}
}
memo[curCity][weekNo] = maxVac;
return maxVac;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1000. Minimum Cost to Merge Stones
Сложность: hard
Имеется n кучек камней, расположенных в ряд. В i-й куче находятся камни stones[i]. Ход состоит в объединении ровно k последовательных куч в одну кучу, и стоимость этого хода равна общему количеству камней в этих k кучах. Верните минимальную стоимость объединения всех куч камней в одну кучу. Если это невозможно, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Проверка на возможность объединения:
Проверьте, можно ли объединить все кучи в одну, если количество куч n не равно 1 по модулю k-1. Если нет, верните -1.
2⃣ Инициализация и динамическое программирование:
Создайте таблицу dp для хранения минимальных затрат на объединение подмассивов камней.
Используйте таблицу prefix для хранения префиксных сумм камней, чтобы быстро вычислять сумму камней в подмассиве.
3⃣ Заполнение таблицы dp:
Заполните таблицу dp минимальными затратами на объединение подмассивов камней, используя динамическое программирование.
Для каждого подмассива длиной от k до n, найдите минимальную стоимость его объединения.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Имеется n кучек камней, расположенных в ряд. В i-й куче находятся камни stones[i]. Ход состоит в объединении ровно k последовательных куч в одну кучу, и стоимость этого хода равна общему количеству камней в этих k кучах. Верните минимальную стоимость объединения всех куч камней в одну кучу. Если это невозможно, верните -1.
Пример:
Input: stones = [3,2,4,1], k = 2
Output: 20
Проверьте, можно ли объединить все кучи в одну, если количество куч n не равно 1 по модулю k-1. Если нет, верните -1.
Создайте таблицу dp для хранения минимальных затрат на объединение подмассивов камней.
Используйте таблицу prefix для хранения префиксных сумм камней, чтобы быстро вычислять сумму камней в подмассиве.
Заполните таблицу dp минимальными затратами на объединение подмассивов камней, используя динамическое программирование.
Для каждого подмассива длиной от k до n, найдите минимальную стоимость его объединения.
public class Solution {
public int MergeStones(int[] stones, int k) {
int n = stones.Length;
if ((n - 1) % (k - 1) != 0) return -1;
int[] prefix = new int[n + 1];
for (int i = 0; i < n; i++) {
prefix[i + 1] = prefix[i] + stones[i];
}
int[,] dp = new int[n, n];
for (int m = k; m <= n; m++) {
for (int i = 0; i <= n - m; i++) {
int j = i + m - 1;
dp[i, j] = int.MaxValue;
for (int t = i; t < j; t += k - 1) {
dp[i, j] = Math.Min(dp[i, j], dp[i, t] + dp[t + 1, j]);
}
if ((j - i) % (k - 1) == 0) {
dp[i, j] += prefix[j + 1] - prefix[i];
}
}
}
return dp[0, n - 1];
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1437. Check If All 1's Are at Least Length K Places Away
Сложность: easy
Дан бинарный массив nums и целое число k. Вернуть true, если все единицы находятся на расстоянии не менее k позиций друг от друга, в противном случае вернуть false.
Пример:
👨💻 Алгоритм:
1⃣ Инициализировать счетчик нулей значением k для учета первого появления единицы.
2⃣ Итерировать по массиву nums, проверяя, если текущий элемент равен 1. Если число нулей между единицами меньше k, вернуть false; иначе сбросить счетчик нулей на 0.
3⃣ Если текущий элемент равен 0, увеличить счетчик нулей. В конце итерации вернуть true.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан бинарный массив nums и целое число k. Вернуть true, если все единицы находятся на расстоянии не менее k позиций друг от друга, в противном случае вернуть false.
Пример:
Input: nums = [1,0,0,0,1,0,0,1], k = 2
Output: true
Explanation: Each of the 1s are at least 2 places away from each other.
public class Solution {
public bool KLengthApart(int[] nums, int k) {
int count = k;
foreach (int num in nums) {
if (num == 1) {
if (count < k) {
return false;
}
count = 0;
} else {
count++;
}
}
return true;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 303. Range Sum Query - Immutable
Сложность: easy
Дан целочисленный массив nums. Обработайте несколько запросов следующего типа:
Вычислите сумму элементов массива nums между индексами left и right включительно, где left <= right.
Реализуйте класс NumArray:
- NumArray(int[] nums) Инициализирует объект с целочисленным массивом nums.
- int sumRange(int left, int right) Возвращает сумму элементов массива nums между индексами left и right включительно (т.е. nums[left] + nums[left + 1] + ... + nums[right]).
Пример:
👨💻 Алгоритм:
1⃣ Инициализация:
Создайте массив sum длиной на один элемент больше, чем массив nums, и заполните его накопленными суммами элементов массива nums.
2⃣ Предварительное вычисление сумм:
Заполните массив sum, где каждый элемент sum[i + 1] является суммой всех предыдущих элементов массива nums до индекса i включительно.
3⃣ Вычисление диапазонной суммы:
Для каждого запроса суммы элементов между индексами left и right используйте разницу между sum[right + 1] и sum[left], чтобы быстро получить результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан целочисленный массив nums. Обработайте несколько запросов следующего типа:
Вычислите сумму элементов массива nums между индексами left и right включительно, где left <= right.
Реализуйте класс NumArray:
- NumArray(int[] nums) Инициализирует объект с целочисленным массивом nums.
- int sumRange(int left, int right) Возвращает сумму элементов массива nums между индексами left и right включительно (т.е. nums[left] + nums[left + 1] + ... + nums[right]).
Пример:
Input
["NumArray", "sumRange", "sumRange", "sumRange"]
[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]
Output
[null, 1, -1, -3]
Создайте массив sum длиной на один элемент больше, чем массив nums, и заполните его накопленными суммами элементов массива nums.
Заполните массив sum, где каждый элемент sum[i + 1] является суммой всех предыдущих элементов массива nums до индекса i включительно.
Для каждого запроса суммы элементов между индексами left и right используйте разницу между sum[right + 1] и sum[left], чтобы быстро получить результат.
public class NumArray {
private int[] sum;
public NumArray(int[] nums) {
sum = new int[nums.Length + 1];
for (int i = 0; i < nums.Length; i++) {
sum[i + 1] = sum[i] + nums[i];
}
}
public int SumRange(int i, int j) {
return sum[j + 1] - sum[i];
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 912. Sort an Array
Сложность: medium
Задав массив целых чисел nums, отсортируйте массив по возрастанию и верните его. Вы должны решить задачу без использования встроенных функций за время O(nlog(n)) и с минимально возможной пространственной сложностью.
Пример:
👨💻 Алгоритм:
1⃣ Используем алгоритм "Сортировка слиянием" (Merge Sort), который обеспечивает время выполнения O(n log n) и минимально возможную пространственную сложность для стабильного сортировочного алгоритма.
2⃣ Разделить массив на две половины.
Рекурсивно отсортировать каждую половину.
3⃣ Слить две отсортированные половины.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Задав массив целых чисел nums, отсортируйте массив по возрастанию и верните его. Вы должны решить задачу без использования встроенных функций за время O(nlog(n)) и с минимально возможной пространственной сложностью.
Пример:
Input: nums = [5,2,3,1]
Output: [1,2,3,5]
Рекурсивно отсортировать каждую половину.
using System;
class Program {
static void MergeSort(int[] nums) {
if (nums.Length > 1) {
int mid = nums.Length / 2;
int[] left_half = new int[mid];
int[] right_half = new int[nums.Length - mid];
Array.Copy(nums, 0, left_half, 0, mid);
Array.Copy(nums, mid, right_half, 0, nums.Length - mid);
MergeSort(left_half);
MergeSort(right_half);
int i = 0, j = 0, k = 0;
while (i < left_half.Length && j < right_half.Length) {
if (left_half[i] < right_half[j]) {
nums[k++] = left_half[i++];
} else {
nums[k++] = right_half[j++];
}
}
while (i < left_half.Length) {
nums[k++] = left_half[i++];
}
while (j < right_half.Length) {
nums[k++] = right_half[j++];
}
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 938. Range Sum of BST
Сложность: easy
Учитывая корневой узел двоичного дерева поиска и два целых числа low и high, верните сумму значений всех узлов со значением в диапазоне [low, high].
Пример:
👨💻 Алгоритм:
1⃣ Если дерево пустое, вернуть 0.
2⃣ Если значение текущего узла меньше low, рекурсивно искать в правом поддереве.
Если значение текущего узла больше high, рекурсивно искать в левом поддереве.
3⃣ Если значение текущего узла в диапазоне [low, high], включить значение узла в сумму и рекурсивно искать в обоих поддеревьях.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Учитывая корневой узел двоичного дерева поиска и два целых числа low и high, верните сумму значений всех узлов со значением в диапазоне [low, high].
Пример:
Input: root = [10,5,15,3,7,null,18], low = 7, high = 15
Output: 32
Если значение текущего узла больше high, рекурсивно искать в левом поддереве.
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
this.val = val;
this.left = left;
this.right = right;
}
}
public class Solution {
public int RangeSumBST(TreeNode root, int low, int high) {
if (root == null) return 0;
if (root.val < low) return RangeSumBST(root.right, low, high);
if (root.val > high) return RangeSumBST(root.left, low, high);
return root.val + RangeSumBST(root.left, low, high) + RangeSumBST(root.right, low, high);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1491. Average Salary Excluding the Minimum and Maximum Salary
Сложность : easy
Вам дан массив уникальных целых чисел
Верните среднюю зарплату сотрудников, исключая минимальную и максимальную зарплату. Ответы, отличающиеся не более чем на 10^-5 от фактического ответа, будут приняты.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация переменных:
Установить minSalary в максимально возможное значение, maxSalary в минимально возможное значение и sum в 0.
2⃣ Итерация по зарплатам:
Для каждой зарплаты добавить её к переменной sum.
Обновить переменную minSalary, если текущая зарплата меньше её значения.
Обновить переменную maxSalary, если текущая зарплата больше её значения.
3⃣ Вычисление среднего значения:
Вернуть значение (sum - minSalary - maxSalary) / (N - 2), предварительно преобразовав числитель и знаменатель в double для точности.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность : easy
Вам дан массив уникальных целых чисел
salary, где salary[i] — это зарплата i-го сотрудника.Верните среднюю зарплату сотрудников, исключая минимальную и максимальную зарплату. Ответы, отличающиеся не более чем на 10^-5 от фактического ответа, будут приняты.
Пример:
Input: salary = [4000,3000,1000,2000]
Output: 2500.00000
Explanation: Minimum salary and maximum salary are 1000 and 4000 respectively.
Average salary excluding minimum and maximum salary is (2000+3000) / 2 = 2500
Установить minSalary в максимально возможное значение, maxSalary в минимально возможное значение и sum в 0.
Для каждой зарплаты добавить её к переменной sum.
Обновить переменную minSalary, если текущая зарплата меньше её значения.
Обновить переменную maxSalary, если текущая зарплата больше её значения.
Вернуть значение (sum - minSalary - maxSalary) / (N - 2), предварительно преобразовав числитель и знаменатель в double для точности.
public class Solution {
public double Average(int[] salary) {
int minSalary = int.MaxValue;
int maxSalary = int.MinValue;
int sum = 0;
foreach (int sal in salary) {
sum += sal;
minSalary = Math.Min(minSalary, sal);
maxSalary = Math.Max(maxSalary, sal);
}
return (double)(sum - minSalary - maxSalary) / (salary.Length - 2);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 673. Number of Longest Increasing Subsequence
Сложность: medium
Дан массив целых чисел nums, верните количество самых длинных строго возрастающих подпоследовательностей.
Пример:
👨💻 Алгоритм:
1⃣ Объявите два массива динамического программирования length и count, и инициализируйте их значениями length[i]=1 и count[i]=1. Итерируйте i от 0 до n−1. Для каждого i итерируйте j от 0 до i−1 и, если nums[j] < nums[i], обновите length[i] и count[i] в зависимости от значений length[j] и count[j].
2⃣ Найдите максимальное значение в массиве length и сохраните его в переменной maxLength. Инициализируйте переменную result = 0.
3⃣ Итерируйте i от 0 до n−1 и, если length[i] = maxLength, добавьте count[i] к result. Верните result.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел nums, верните количество самых длинных строго возрастающих подпоследовательностей.
Пример:
Input: n = 1, presses = 1
Output: 2
Explanation: Status can be:
- [off] by pressing button 1
- [on] by pressing button 2
public class Solution {
public int FindNumberOfLIS(int[] nums) {
int n = nums.Length;
int[] length = new int[n];
int[] count = new int[n];
Array.Fill(length, 1);
Array.Fill(count, 1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
if (length[j] + 1 > length[i]) {
length[i] = length[j] + 1;
count[i] = 0;
}
if (length[j] + 1 == length[i]) {
count[i] += count[j];
}
}
}
}
int maxLength = length.Max();
int result = 0;
for (int i = 0; i < n; i++) {
if (length[i] == maxLength) {
result += count[i];
}
}
return result;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Новая фича на easyoffer – Автоотлики
Вы автоматически откликаетесь на подходящие вам вакансии. Попробуйте её бесплатно и начните получать больше предложений о работе.
🚀 Запуск занимаем всего 3 минуты, а экономит очень много времени
🛡 Это безопасно: easyoffer официально одобрен HeadHunter и прошел его модерацию.
🥷🏻 Автоотклик незаметен для рекртера. Автоотклик ничем не отличается от обычного отклика, который вы делаете вручную
Рекрутеры давно используют автоматизацию для поиска кандидатов. Так почему вы должны откликаться вручную?
💡Совет – Добавьте шаблон сопроводительного письма, чтобы откликаться на большее количество вакансий (на некоторые вакансии нельзя откликнуться без сопроводительного)
Попробовать бесплатно → https://easyoffer.ru/autoapply
Вы автоматически откликаетесь на подходящие вам вакансии. Попробуйте её бесплатно и начните получать больше предложений о работе.
🚀 Запуск занимаем всего 3 минуты, а экономит очень много времени
🛡 Это безопасно: easyoffer официально одобрен HeadHunter и прошел его модерацию.
🥷🏻 Автоотклик незаметен для рекртера. Автоотклик ничем не отличается от обычного отклика, который вы делаете вручную
Рекрутеры давно используют автоматизацию для поиска кандидатов. Так почему вы должны откликаться вручную?
💡Совет – Добавьте шаблон сопроводительного письма, чтобы откликаться на большее количество вакансий (на некоторые вакансии нельзя откликнуться без сопроводительного)
Попробовать бесплатно → https://easyoffer.ru/autoapply
Задача: 284. Peeking Iterator
Сложность: medium
Создайте итератор, который поддерживает операцию peek (просмотр следующего элемента) на существующем итераторе, помимо операций hasNext (проверка наличия следующего элемента) и next (получение следующего элемента).
Реализуйте класс PeekingIterator:
PeekingIterator(Iterator<int> nums): Инициализирует объект с заданным итератором целых чисел.
int next(): Возвращает следующий элемент в массиве и перемещает указатель на следующий элемент.
boolean hasNext(): Возвращает true, если в массиве еще есть элементы.
int peek(): Возвращает следующий элемент в массиве без перемещения указателя.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация итератора:
В конструкторе класса PeekingIterator инициализируйте итератор и проверьте, есть ли следующий элемент. Если есть, установите его как next, иначе установите next в null.
2⃣ Операция peek:
Метод peek возвращает значение next, не перемещая указатель итератора.
3⃣ Операции next и hasNext:
Метод next возвращает текущее значение next, обновляет next к следующему элементу в итераторе и перемещает указатель итератора. Если нет следующего элемента, бросает исключение NoSuchElementException.
Метод hasNext возвращает true, если next не равно null, и false в противном случае.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Создайте итератор, который поддерживает операцию peek (просмотр следующего элемента) на существующем итераторе, помимо операций hasNext (проверка наличия следующего элемента) и next (получение следующего элемента).
Реализуйте класс PeekingIterator:
PeekingIterator(Iterator<int> nums): Инициализирует объект с заданным итератором целых чисел.
int next(): Возвращает следующий элемент в массиве и перемещает указатель на следующий элемент.
boolean hasNext(): Возвращает true, если в массиве еще есть элементы.
int peek(): Возвращает следующий элемент в массиве без перемещения указателя.
Пример:
Input
["PeekingIterator", "next", "peek", "next", "next", "hasNext"]
[[[1, 2, 3]], [], [], [], [], []]
Output
[null, 1, 2, 2, 3, false]
Explanation
PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1,2,3]
peekingIterator.next(); // return 1, the pointer moves to the next element [1,2,3].
peekingIterator.peek(); // return 2, the pointer does not move [1,2,3].
peekingIterator.next(); // return 2, the pointer moves to the next element [1,2,3]
peekingIterator.next(); // return 3, the pointer moves to the next element [1,2,3]
peekingIterator.hasNext(); // return False
В конструкторе класса PeekingIterator инициализируйте итератор и проверьте, есть ли следующий элемент. Если есть, установите его как next, иначе установите next в null.
Метод peek возвращает значение next, не перемещая указатель итератора.
Метод next возвращает текущее значение next, обновляет next к следующему элементу в итераторе и перемещает указатель итератора. Если нет следующего элемента, бросает исключение NoSuchElementException.
Метод hasNext возвращает true, если next не равно null, и false в противном случае.
using System;
using System.Collections.Generic;
public class PeekingIterator {
private IEnumerator<int> iterator;
private bool hasPeeked;
private int peekedElement;
public PeekingIterator(IEnumerator<int> iterator) {
this.iterator = iterator;
}
public int Next() {
if (hasPeeked) {
hasPeeked = false;
return peekedElement;
}
return iterator.MoveNext() ? iterator.Current : throw new InvalidOperationException();
}
public bool HasNext() {
return hasPeeked || iterator.MoveNext();
}
public int Peek() {
if (!hasPeeked) {
hasPeeked = iterator.MoveNext();
peekedElement = iterator.Current;
}
return peekedElement;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 387. First Unique Character in a String
Сложность: easy
Дана строка s, найдите первый неповторяющийся символ в ней и верните его индекс. Если такого символа не существует, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Постройте хеш-таблицу, где ключами являются символы строки, а значениями — количество их появлений. Для этого пройдите по строке и для каждого символа увеличивайте его счетчик в хеш-таблице.
2⃣ Пройдите по строке снова и проверьте для каждого символа, является ли его количество появлений в хеш-таблице равным 1.
3⃣ Если найдется символ с количеством появлений, равным 1, верните его индекс. Если такой символ не найден, верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дана строка s, найдите первый неповторяющийся символ в ней и верните его индекс. Если такого символа не существует, верните -1.
Пример:
Input: s = "leetcode"
Output: 0
using System;
using System.Collections.Generic;
public class Solution {
private int[] original;
private int[] array;
private Random rand = new Random();
public Solution(int[] nums) {
array = (int[])nums.Clone();
original = (int[])nums.Clone();
}
public int[] Reset() {
array = (int[])original.Clone();
return original;
}
public int[] Shuffle() {
for (int i = 0; i < array.Length; i++) {
int randIndex = rand.Next(i, array.Length);
int temp = array[i];
array[i] = array[randIndex];
array[randIndex] = temp;
}
return array;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 242. Valid Anagram
Сложность: easy
Даны две строки s и t, верните true, если t является анаграммой s, и false в противном случае.
Анаграмма — это слово или фраза, сформированная путём перестановки букв другого слова или фразы, обычно используя все исходные буквы ровно один раз.
Пример:
👨💻 Алгоритм:
1⃣ Создайте массив размером 26 для подсчета частот каждой буквы (поскольку s и t содержат только буквы от 'a' до 'z').
2⃣ Пройдитесь по строке s, увеличивая счетчик соответствующей буквы. Затем пройдитесь по строке t, уменьшая счетчик для каждой буквы.
3⃣ Проверьте, не опустился ли счетчик ниже нуля во время обхода строки t. Если это произошло, значит в t есть лишняя буква, которой нет в s, и следует вернуть false. Если после проверки всех букв все счетчики равны нулю, возвращайте true, указывая на то, что t является анаграммой s.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Даны две строки s и t, верните true, если t является анаграммой s, и false в противном случае.
Анаграмма — это слово или фраза, сформированная путём перестановки букв другого слова или фразы, обычно используя все исходные буквы ровно один раз.
Пример:
Input: s = "anagram", t = "nagaram"
Output: true
public bool IsAnagram(string s, string t) {
if (s.Length != t.Length) {
return false;
}
int[] table = new int[26];
for (int i = 0; i < s.Length; i++) {
table[s[i] - 'a']++;
table[t[i] - 'a']--;
}
foreach (int count in table) {
if (count != 0) return false;
}
return true;
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 168. Excel Sheet Column Title
Сложность: easy
Дано целое число columnNumber, верните соответствующий заголовок столбца, как он отображается в таблице Excel.
Например:
A -> 1
B -> 2
C -> 3
Z -> 26
AA -> 27
AB -> 28
Пример:
👨💻 Алгоритм:
1⃣ Инициализация пустой строки ans:
Создайте пустую строку ans, которая будет хранить заголовок столбца.
2⃣ Циклическое преобразование числа в буквы:
Пока columnNumber больше 0, выполняйте следующие действия:
Вычтите 1 из columnNumber для корректировки индекса (Excel использует 1-индексацию).
Найдите символ, соответствующий остатку от деления columnNumber на 26, и добавьте его в начало строки ans.
Присвойте columnNumber значение от деления columnNumber на 26
3⃣ Переворот и возврат результата:
Так как символы добавляются в начало строки, то по завершению цикла строка ans содержит заголовок столбца в обратном порядке. Переверните строку ans, чтобы представить её в правильном порядке.
Верните полученный заголовок столбца.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дано целое число columnNumber, верните соответствующий заголовок столбца, как он отображается в таблице Excel.
Например:
A -> 1
B -> 2
C -> 3
Z -> 26
AA -> 27
AB -> 28
Пример:
Input: columnNumber = 1
Output: "A"
Создайте пустую строку ans, которая будет хранить заголовок столбца.
Пока columnNumber больше 0, выполняйте следующие действия:
Вычтите 1 из columnNumber для корректировки индекса (Excel использует 1-индексацию).
Найдите символ, соответствующий остатку от деления columnNumber на 26, и добавьте его в начало строки ans.
Присвойте columnNumber значение от деления columnNumber на 26
Так как символы добавляются в начало строки, то по завершению цикла строка ans содержит заголовок столбца в обратном порядке. Переверните строку ans, чтобы представить её в правильном порядке.
Верните полученный заголовок столбца.
public class Solution {
public string ConvertToTitle(int columnNumber) {
string ans = "";
while (columnNumber > 0) {
columnNumber--;
ans = ((char)((columnNumber) % 26 + 'A')) + ans;
columnNumber = (columnNumber) / 26;
}
return ans;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 314. Binary Tree Vertical Order Traversal
Сложность: medium
Дан корень бинарного дерева, верните вертикальный порядок обхода значений его узлов (т.е. сверху вниз, столбец за столбцом).
Если два узла находятся в одной строке и столбце, порядок должен быть слева направо.
Пример:
👨💻 Алгоритм:
1⃣ Создайте хэш-таблицу с именем columnTable для отслеживания результатов.
2⃣ Инициализируйте очередь, поместив в нее корневой узел вместе с его индексом столбца (0). Выполните обход в ширину (BFS), извлекая элементы из очереди. На каждой итерации извлекайте элемент, состоящий из узла и соответствующего индекса столбца. Если узел не пуст, добавьте его значение в columnTable. Затем поместите дочерние узлы с их индексами столбцов (т.е. column-1 и column+1) в очередь.
3⃣ После завершения BFS обхода получите хэш-таблицу, содержащую значения узлов, сгруппированные по индексам столбцов. Для каждой группы значений отсортируйте их по индексам строк. Отсортируйте хэш-таблицу по ключам (индексам столбцов) в порядке возрастания и верните результаты по столбцам.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень бинарного дерева, верните вертикальный порядок обхода значений его узлов (т.е. сверху вниз, столбец за столбцом).
Если два узла находятся в одной строке и столбце, порядок должен быть слева направо.
Пример:
Input: root = [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]
using System;
using System.Collections.Generic;
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int x) { val = x; }
}
public class Solution {
public IList<IList<int>> VerticalOrder(TreeNode root) {
IList<IList<int>> output = new List<IList<int>>();
if (root == null) {
return output;
}
Dictionary<int, List<int>> columnTable = new Dictionary<int, List<int>>();
Queue<(TreeNode, int)> queue = new Queue<(TreeNode, int)>();
int column = 0;
queue.Enqueue((root, column));
while (queue.Count > 0) {
var (node, col) = queue.Dequeue();
if (node != null) {
if (!columnTable.ContainsKey(col)) {
columnTable[col] = new List<int>();
}
columnTable[col].Add(node.val);
queue.Enqueue((node.left, col - 1));
queue.Enqueue((node.right, col + 1));
}
}
var sortedKeys = new List<int>(columnTable.Keys);
sortedKeys.Sort();
foreach (var key in sortedKeys) {
output.Add(columnTable[key]);
}
return output;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1057. Campus Bikes
Сложность: medium
В городке, изображенном на плоскости X-Y, есть n рабочих и m велосипедов, причем n <= m. Вам дан массив workers длины n, где workers[i] = [xi, yi] - положение i-го рабочего. Вам также дан массив bikes длины m, где bikes[j] = [xj, yj] - позиция j-го велосипеда. Все заданные позиции уникальны. Назначаем велосипед каждому работнику. Среди доступных велосипедов и работников мы выбираем пару (workeri, bikej) с наименьшим манхэттенским расстоянием между ними и назначаем велосипед этому работнику. Если существует несколько пар (workeri, bikej) с одинаковым наименьшим манхэттенским расстоянием, мы выбираем пару с наименьшим индексом работника. Если существует несколько способов сделать это, мы выбираем пару с наименьшим индексом велосипеда. Повторяем этот процесс до тех пор, пока не останется свободных работников. Возвращаем массив answer длины n, где answer[i] - индекс (с индексом 0) велосипеда, на который назначен i-й работник. Манхэттенское расстояние между двумя точками p1 и p2 равно Manhattan(p1, p2) = |p1.x - p2.x| + |p1.y - p2.y|.
Пример:
👨💻 Алгоритм:
1⃣ Для каждой пары (работник, велосипед) вычисли Манхэттенское расстояние и сохрани все пары вместе с расстоянием в список.
2⃣ Отсортируй список пар по расстоянию, а затем по индексу работника и велосипеда.
Назначь велосипеды работникам, следуя отсортированному списку пар и отслеживая, какие работники и велосипеды уже были использованы.
3⃣ Заполни и верни массив назначений.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
В городке, изображенном на плоскости X-Y, есть n рабочих и m велосипедов, причем n <= m. Вам дан массив workers длины n, где workers[i] = [xi, yi] - положение i-го рабочего. Вам также дан массив bikes длины m, где bikes[j] = [xj, yj] - позиция j-го велосипеда. Все заданные позиции уникальны. Назначаем велосипед каждому работнику. Среди доступных велосипедов и работников мы выбираем пару (workeri, bikej) с наименьшим манхэттенским расстоянием между ними и назначаем велосипед этому работнику. Если существует несколько пар (workeri, bikej) с одинаковым наименьшим манхэттенским расстоянием, мы выбираем пару с наименьшим индексом работника. Если существует несколько способов сделать это, мы выбираем пару с наименьшим индексом велосипеда. Повторяем этот процесс до тех пор, пока не останется свободных работников. Возвращаем массив answer длины n, где answer[i] - индекс (с индексом 0) велосипеда, на который назначен i-й работник. Манхэттенское расстояние между двумя точками p1 и p2 равно Manhattan(p1, p2) = |p1.x - p2.x| + |p1.y - p2.y|.
Пример:
Input: workers = [[0,0],[2,1]], bikes = [[1,2],[3,3]]
Output: [1,0]
Назначь велосипеды работникам, следуя отсортированному списку пар и отслеживая, какие работники и велосипеды уже были использованы.
public class Solution {
public int[] AssignBikes(int[][] workers, int[][] bikes) {
var pairs = new List<(int distance, int workerIdx, int bikeIdx)>();
for (int i = 0; i < workers.Length; i++) {
for (int j = 0; j < bikes.Length; j++) {
int distance = Math.Abs(workers[i][0] - bikes[j][0]) + Math.Abs(workers[i][1] - bikes[j][1]);
pairs.Add((distance, i, j));
}
}
pairs.Sort((a, b) => {
int result = a.distance.CompareTo(b.distance);
if (result == 0) {
result = a.workerIdx.CompareTo(b.workerIdx);
if (result == 0) {
result = a.bikeIdx.CompareTo(b.bikeIdx);
}
}
return result;
});
int[] result = new int[workers.Length];
bool[] bikeTaken = new bool[bikes.Length];
bool[] workerAssigned = new bool[workers.Length];
Array.Fill(result, -1);
foreach (var pair in pairs) {
if (!workerAssigned[pair.workerIdx] && !bikeTaken[pair.bikeIdx]) {
result[pair.workerIdx] = pair.bikeIdx;
bikeTaken[pair.bikeIdx] = true;
workerAssigned[pair.workerIdx] = true;
}
}
return result;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 897. Increasing Order Search Tree
Сложность: easy
Задав корень дерева двоичного поиска, перестройте дерево по порядку так, чтобы самый левый узел дерева теперь был корнем дерева, а каждый узел не имел левого и только одного правого дочернего узла.
Пример:
👨💻 Алгоритм:
1⃣ Выполнить обход дерева в порядке in-order, чтобы получить список узлов.
2⃣ Перестроить дерево, устанавливая каждый узел из списка как правый дочерний элемент предыдущего узла и устанавливая левые дочерние элементы в null.
3⃣ Вернуть новый корень дерева (первый элемент списка).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Задав корень дерева двоичного поиска, перестройте дерево по порядку так, чтобы самый левый узел дерева теперь был корнем дерева, а каждый узел не имел левого и только одного правого дочернего узла.
Пример:
Input: root = [5,3,6,2,4,null,8,1,null,null,null,7,9]
Output: [1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]
using System;
using System.Collections.Generic;
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
this.val = val;
this.left = left;
this.right = right;
}
}
public class Solution {
public TreeNode IncreasingBST(TreeNode root) {
List<TreeNode> nodes = new List<TreeNode>();
Inorder(root, nodes);
for (int i = 0; i < nodes.Count - 1; i++) {
nodes[i].left = null;
nodes[i].right = nodes[i + 1];
}
nodes[nodes.Count - 1].left = null;
nodes[nodes.Count - 1].right = null;
return nodes[0];
}
private void Inorder(TreeNode node, List<TreeNode> nodes) {
if (node == null) return;
Inorder(node.left, nodes);
nodes.Add(node);
Inorder(node.right, nodes);
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 187. Repeated DNA Sequences
Сложность: medium
ДНК состоит из серии нуклеотидов, обозначаемых как 'A', 'C', 'G' и 'T'.
Например, "ACGAATTCCG" — это последовательность ДНК.
При изучении ДНК полезно определять повторяющиеся последовательности внутри молекулы ДНК.
Дана строка s, представляющая последовательность ДНК. Верните все последовательности длиной 10 букв (подстроки), которые встречаются более одного раза в молекуле ДНК. Ответ можно возвращать в любом порядке.
Пример:
👨💻 Алгоритм:
1⃣ Перебираем начальные позиции последовательности от 1 до 𝑁−𝐿, где 𝑁 — длина строки, а 𝐿 — длина подстроки (в данном случае 10):
Если начальная позиция 𝑠𝑡𝑎𝑟𝑡==0, вычисляем хеш первой последовательности 𝑠[0:𝐿].
В противном случае вычисляем скользящий хеш из предыдущего значения хеша.
2⃣ Проверяем хеш в хешсете:
Если хеш уже существует в хешсете, значит, мы нашли повторяющуюся последовательность, и пора обновить вывод.
В противном случае добавляем хеш в хешсет.
3⃣ Возвращаем список вывода, содержащий все повторяющиеся последовательности.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
ДНК состоит из серии нуклеотидов, обозначаемых как 'A', 'C', 'G' и 'T'.
Например, "ACGAATTCCG" — это последовательность ДНК.
При изучении ДНК полезно определять повторяющиеся последовательности внутри молекулы ДНК.
Дана строка s, представляющая последовательность ДНК. Верните все последовательности длиной 10 букв (подстроки), которые встречаются более одного раза в молекуле ДНК. Ответ можно возвращать в любом порядке.
Пример:
Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
Output: ["AAAAACCCCC","CCCCCAAAAA"]
Если начальная позиция 𝑠𝑡𝑎𝑟𝑡==0, вычисляем хеш первой последовательности 𝑠[0:𝐿].
В противном случае вычисляем скользящий хеш из предыдущего значения хеша.
Если хеш уже существует в хешсете, значит, мы нашли повторяющуюся последовательность, и пора обновить вывод.
В противном случае добавляем хеш в хешсет.
public class Solution {
public IList<string> FindRepeatedDnaSequences(string s) {
int L = 10, n = s.Length;
if (n <= L) return new List<string>();
int a = 4, aL = (int)Math.Pow(a, L);
Dictionary<char, int> toInt = new Dictionary<char, int>{{'A', 0}, {'C', 1}, {'G', 2}, {'T', 3}};
int[] nums = s.Select(c => toInt[c]).ToArray();
int h = 0;
HashSet<int> seen = new HashSet<int>();
HashSet<string> output = new HashSet<string>();
for (int start = 0; start < n - L + 1; start++) {
if (start != 0)
h = h * a - nums[start - 1] * aL + nums[start + L - 1];
else
for (int i = 0; i < L; i++)
h = h * a + nums[i];
if (seen.Contains(h))
output.Add(s.Substring(start, L));
seen.Add(h);
}
return output.ToList();
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1095. Find in Mountain Array
Сложность: hard
Массив arr является горным массивом тогда и только тогда, когда:
Длина массива arr >= 3.
Существует некоторое i с 0 < i < arr.length - 1 такое, что:
arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
Дан горный массив mountainArr, верните минимальный индекс, такой что mountainArr.get(index) == target. Если такого индекса не существует, верните -1.
Вы не можете напрямую обращаться к массиву. Вы можете использовать интерфейс MountainArray:
MountainArray.get(k) возвращает элемент массива на индексе k (индексация начинается с 0).
MountainArray.length() возвращает длину массива.
Решения, использующие более 100 вызовов MountainArray.get, будут оценены как неправильные. Также любые решения, которые пытаются обойти ограничение, будут дисквалифицированы.
Пример:
👨💻 Алгоритм:
1⃣ Найти индекс пика: Инициализируем два указателя low и high, где low начинается с 1, а high — с длины массива минус 2. Используем бинарный поиск для нахождения пикового элемента: если элемент в середине меньше следующего элемента, то пиковый элемент находится справа, иначе он находится слева. Продолжаем сужать диапазон поиска до тех пор, пока low не станет равным high. Это и будет индекс пика.
2⃣ Бинарный поиск в возрастающей части массива: Устанавливаем указатели low и high для поиска в диапазоне от 0 до пикового индекса. Проводим обычный бинарный поиск: если значение в середине меньше целевого значения, перемещаем low вправо, иначе перемещаем high влево. По завершении поиска проверяем, равно ли значение по индексу low целевому значению. Если да, возвращаем индекс, иначе продолжаем.
3⃣ Бинарный поиск в убывающей части массива: Устанавливаем указатели low и high для поиска в диапазоне от пикового индекса плюс 1 до конца массива. Проводим бинарный поиск, но с учетом убывающей последовательности: если значение в середине больше целевого значения, перемещаем low вправо, иначе перемещаем high влево. По завершении поиска проверяем, равно ли значение по индексу low целевому значению. Если да, возвращаем индекс. Если значение не найдено, возвращаем -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Массив arr является горным массивом тогда и только тогда, когда:
Длина массива arr >= 3.
Существует некоторое i с 0 < i < arr.length - 1 такое, что:
arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
Дан горный массив mountainArr, верните минимальный индекс, такой что mountainArr.get(index) == target. Если такого индекса не существует, верните -1.
Вы не можете напрямую обращаться к массиву. Вы можете использовать интерфейс MountainArray:
MountainArray.get(k) возвращает элемент массива на индексе k (индексация начинается с 0).
MountainArray.length() возвращает длину массива.
Решения, использующие более 100 вызовов MountainArray.get, будут оценены как неправильные. Также любые решения, которые пытаются обойти ограничение, будут дисквалифицированы.
Пример:
Input: array = [1,2,3,4,5,3,1], target = 3
Output: 2
Explanation: 3 exists in the array, at index=2 and index=5. Return the minimum index, which is 2.
public class Solution {
public int FindInMountainArray(int target, MountainArray mountainArr) {
int length = mountainArr.length();
int low = 1, high = length - 2;
while (low != high) {
int mid = (low + high) / 2;
if (mountainArr.get(mid) < mountainArr.get(mid + 1)) {
low = mid + 1;
} else {
high = mid;
}
}
int peak = low;
low = 0;
high = peak;
while (low < high) {
int mid = (low + high) / 2;
if (mountainArr.get(mid) < target) {
low = mid + 1;
} else {
high = mid;
}
}
if (mountainArr.get(low) == target) {
return low;
}
low = peak + 1;
high = length - 1;
while (low < high) {
int mid = (low + high) / 2;
if (mountainArr.get(mid) > target) {
low = mid + 1;
} else {
high = mid;
}
}
if (mountainArr.get(low) == target) {
return low;
}
return -1;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 663. Equal Tree Partition
Сложность: medium
Дан корень бинарного дерева. Верните true, если можно разделить дерево на два дерева с равными суммами значений после удаления ровно одного ребра из исходного дерева.
Пример:
👨💻 Алгоритм:
1⃣ Вычисление общей суммы:
Напишите функцию для вычисления общей суммы всех узлов дерева.
2⃣ Проверка возможности разделения:
Напишите функцию, чтобы рекурсивно проверить, может ли поддерево быть равно половине общей суммы. Если такое поддерево найдено, значит дерево можно разделить на две части с равными суммами.
3⃣ Валидация и возврат результата:
Проверьте, что общая сумма четная (так как только в этом случае возможно её разделение на две равные части), и используйте функцию проверки поддерева, чтобы определить, можно ли разделить дерево на две части с равными суммами.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень бинарного дерева. Верните true, если можно разделить дерево на два дерева с равными суммами значений после удаления ровно одного ребра из исходного дерева.
Пример:
Input: root = [5,10,10,null,null,2,3]
Output: true
Напишите функцию для вычисления общей суммы всех узлов дерева.
Напишите функцию, чтобы рекурсивно проверить, может ли поддерево быть равно половине общей суммы. Если такое поддерево найдено, значит дерево можно разделить на две части с равными суммами.
Проверьте, что общая сумма четная (так как только в этом случае возможно её разделение на две равные части), и используйте функцию проверки поддерева, чтобы определить, можно ли разделить дерево на две части с равными суммами.
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int x) { val = x; }
}
public class Solution {
public bool CheckEqualTree(TreeNode root) {
int totalSum = SumTree(root);
if (totalSum % 2 != 0) return false;
int target = totalSum / 2;
return CheckSubtreeSum(root, target, root);
}
private int SumTree(TreeNode node) {
if (node == null) return 0;
return node.val + SumTree(node.left) + SumTree(node.right);
}
private bool CheckSubtreeSum(TreeNode node, int target, TreeNode root) {
if (node == null) return false;
if (node != root && SumTree(node) == target) {
return true;
}
return CheckSubtreeSum(node.left, target, root) || CheckSubtreeSum(node.right, target, root);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 711. Number of Distinct Islands II
Сложность: hard
Вам дана двоичная матричная сетка m x n. Остров - это группа 1 (представляющая сушу), соединенных в четырех направлениях (горизонтальном или вертикальном). Можно предположить, что все четыре края сетки окружены водой. Остров считается одинаковым с другим, если они имеют одинаковую форму, или имеют одинаковую форму после поворота (только на 90, 180 или 270 градусов) или отражения (влево/вправо или вверх/вниз). Верните количество разных островов.
Пример:
👨💻 Алгоритм:
1⃣ Пройдите по каждому элементу матрицы, если найдена земля (1), выполните DFS для обнаружения всех связанных с этим островом земель и сохраните форму острова.
2⃣ Нормализуйте форму острова, применив все возможные повороты и отражения, чтобы найти каноническую форму.
3⃣ Используйте множество для хранения всех уникальных канонических форм и верните размер этого множества.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Вам дана двоичная матричная сетка 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
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
public int NumDistinctIslands2(int[][] grid) {
var uniqueIslands = new HashSet<string>();
for (int i = 0; i < grid.Length; i++) {
for (int j = 0; j < grid[0].Length; j++) {
if (grid[i][j] == 1) {
var shape = new List<(int, int)>();
Dfs(grid, i, j, i, j, shape);
uniqueIslands.Add(Normalize(shape));
}
}
}
return uniqueIslands.Count;
}
private void Dfs(int[][] grid, int i, int j, int baseI, int baseJ, List<(int, int)> shape) {
if (i < 0 || i >= grid.Length || j < 0 || j >= grid[0].Length || grid[i][j] == 0) {
return;
}
grid[i][j] = 0;
shape.Add((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);
}
private string Normalize(List<(int, int)> shape) {
var shapes = new List<List<(int, int)>>();
for (int i = 0; i < 8; i++) {
shapes.Add(new List<(int, int)>());
}
foreach (var (x, y) in shape) {
shapes[0].Add((x, y));
shapes[1].Add((x, -y));
shapes[2].Add((-x, y));
shapes[3].Add((-x, -y));
shapes[4].Add((y, x));
shapes[5].Add((y, -x));
shapes[6].Add((-y, x));
shapes[7].Add((-y, -x));
}
foreach (var s in shapes) {
s.Sort();
}
string minShape = string.Join(";", shapes[0].Select(p => $"{p.Item1},{p.Item2}"));
foreach (var s in shapes) {
string sStr = string.Join(";", s.Select(p => $"{p.Item1},{p.Item2}"));
if (string.Compare(sStr, minShape, StringComparison.Ordinal) < 0) {
minShape = sStr;
}
}
return minShape;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM