JavaScript | LeetCode
9.59K subscribers
204 photos
1 video
1.08K links
Cайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp

Тесты t.iss.one/+T0COHtFzCJkwMDUy
Вопросы собесов t.iss.one/+kXKgJEjRUww3N2Ni
Вакансии t.iss.one/+CgCAzIyGHHg0Nzky
Download Telegram
Задача: 587. Erect the Fence
Сложность: hard

Вам дан массив trees, где trees[i] = [xi, yi] представляет местоположение дерева в саду.
Оградите весь сад с использованием минимальной длины веревки, так как это дорого. Сад хорошо огорожен только в том случае, если все деревья окружены.
Верните координаты деревьев, которые находятся точно на периметре ограды. Вы можете вернуть ответ в любом порядке.

Пример:
Input: trees = [[1,1],[2,2],[2,0],[2,4],[3,3],[4,2]]
Output: [[1,1],[2,0],[4,2],[3,3],[2,4]]
Explanation: All the trees will be on the perimeter of the fence except the tree at [2, 2], which will be inside the fence.


👨‍💻 Алгоритм:

1⃣ Сортировка точек и построение нижней оболочки:
Отсортируйте точки по их x-координатам, а в случае совпадения x-координат, по y-координатам.
Постройте нижнюю оболочку, добавляя точки к оболочке и удаляя последние точки, если они не образуют против часовой стрелки поворот.

2⃣ Построение верхней оболочки:
Пройдитесь по точкам в обратном порядке, чтобы построить верхнюю оболочку.
Добавляйте точки к оболочке и удаляйте последние точки, если они не образуют против часовой стрелки поворот.

3⃣ Удаление дублирующих элементов и возврат результата:
Используйте HashSet, чтобы удалить дублирующиеся точки из стека.
Преобразуйте результат в массив и верните его.

😎 Решение:
var orientation = function(p, q, r) {
return (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);
};

var outerTrees = function(points) {
points.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
const hull = [];

for (let point of points) {
while (hull.length >= 2 && orientation(hull[hull.length - 2], hull[hull.length - 1], point) > 0) {
hull.pop();
}
hull.push(point);
}

hull.pop();

for (let i = points.length - 1; i >= 0; i--) {
while (hull.length >= 2 && orientation(hull[hull.length - 2], hull[hull.length - 1], points[i]) > 0) {
hull.pop();
}
hull.push(points[i]);
}

const uniqueHull = new Set(hull.map(JSON.stringify));
return Array.from(uniqueHull).map(JSON.parse);
};


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 689. Maximum Sum of 3 Non-Overlapping Subarrays
Сложность: hard

Дан целочисленный массив nums и целое число k. Найдите три непересекающихся подмассива длины k с максимальной суммой и верните их.

Верните результат в виде списка индексов, представляющих начальную позицию каждого интервала (нумерация с 0). Если существует несколько ответов, верните лексикографически наименьший.

Пример:
Input: nums = [1,2,1,2,6,7,5,1], k = 2
Output: [0,3,5]
Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.


👨‍💻 Алгоритм:

1⃣Предположим, что фиксирован j. Нам нужно узнать на интервалах i∈[0,j−k] и l∈[j+k,len(W)−1], где наибольшее значение W[i] (и соответственно W[l]) встречается первым (то есть, с наименьшим индексом).

2⃣Мы можем решить эту задачу с помощью динамического программирования. Например, если мы знаем, что i - это место, где наибольшее значение W[i] встречается первым на [0,5], то на [0,6] первое появление наибольшего W[i] должно быть либо i, либо 6. Если, скажем, 6 лучше, тогда мы устанавливаем best = 6. В конце left[z] будет первым вхождением наибольшего значения W[i] на интервале i∈[0,z], а right[z] будет таким же, но на интервале i∈[z,len(W)−1].

3⃣Это означает, что для некоторого выбора j, кандидат на ответ должен быть (left[j - k], j, right[j + k]). Мы выбираем кандидата, который дает максимальное значение W[i] + W[j] + W[l].

😎 Решение:
class Solution {
maxSumOfThreeSubarrays(nums, k) {
const W = new Array(nums.length - k + 1).fill(0);
let currSum = 0;
for (let i = 0; i < nums.length; i++) {
currSum += nums[i];
if (i >= k) {
currSum -= nums[i - k];
}
if (i >= k - 1) {
W[i - k + 1] = currSum;
}
}

const left = new Array(W.length).fill(0);
let best = 0;
for (let i = 0; i < W.length; i++) {
if (W[i] > W[best]) best = i;
left[i] = best;
}

const right = new Array(W.length).fill(0);
best = W.length - 1;
for (let i = W.length - 1; i >= 0; i--) {
if (W[i] >= W[best]) best = i;
right[i] = best;
}

const ans = [-1, -1, -1];
for (let j = k; j < W.length - k; j++) {
const i = left[j - k];
const l = right[j + k];
if (ans[0] === -1 || W[i] + W[j] + W[l] > W[ans[0]] + W[ans[1]] + W[ans[2]]) {
ans[0] = i;
ans[1] = j;
ans[2] = l;
}
}
return ans;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1277. Count Square Submatrices with All Ones
Сложность: medium

Если задана матрица m * n из единиц и нулей, верните, сколько квадратных подматриц имеют все единицы.

Пример:
Input: matrix =
[
[0,1,1,1],
[1,1,1,1],
[0,1,1,1]
]
Output: 15


👨‍💻 Алгоритм:

1⃣Создайте вспомогательную матрицу dp таких же размеров, что и исходная матрица, для хранения размеров максимальных квадратов.

2⃣Пройдите по каждому элементу матрицы и обновите dp следующим образом: если элемент равен 1, то dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1.

3⃣Суммируйте все значения в dp, чтобы получить количество квадратных подматриц, состоящих из всех единиц.

😎 Решение:
var countSquares = function(matrix) {
let m = matrix.length, n = matrix[0].length;
let dp = Array.from({ length: m }, () => Array(n).fill(0));
let count = 0;

for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (matrix[i][j] === 1) {
if (i === 0 || j === 0) {
dp[i][j] = 1;
} else {
dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1;
}
count += dp[i][j];
}
}
}

return count;
};


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 60. Permutation Sequence
Сложность: hard

Множество [1, 2, 3, ..., n] содержит в общей сложности n! уникальных перестановок.
Списком и маркировкой всех перестановок по порядку, мы получаем следующую последовательность для n = 3:
"123"
"132"
"213"
"231"
"312"
"321"
Дано n и k, верните k-ю перестановку последовательности.

Пример:
Input: n = 3, k = 3
Output: "213"


👨‍💻 Алгоритм:

1️⃣Сгенерируйте входной массив nums чисел от 1 до N.

2️⃣Вычислите все факториальные основы от 0 до (N−1)!.

3️⃣Уменьшите k на 1, чтобы значение попало в интервал (0, N!−1).

😎 Решение:
var getPermutation = function (n, k) {
let factorials = new Array(n);
let nums = ["1"];
factorials[0] = 1;
for (let i = 1; i < n; ++i) {
factorials[i] = factorials[i - 1] * i;
nums.push((i + 1).toString());
}
--k;
let output = "";
for (let i = n - 1; i > -1; --i) {
let idx = Math.floor(k / factorials[i]);
k -= idx * factorials[i];
output += nums[idx];
nums.splice(idx, 1);
}
return output;
};


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 953. Verifying an Alien Dictionary
Сложность: hard

В инопланетном языке, как ни странно, тоже используются английские строчные буквы, но, возможно, в другом порядке. Порядок алфавита - это некоторая перестановка строчных букв. Учитывая последовательность слов, написанных на инопланетном языке, и порядок алфавита, верните true тогда и только тогда, когда данные слова отсортированы лексикографически на этом инопланетном языке.

Пример:
Input: words = ["hello","leetcode"], order = "hlabcdefgijkmnopqrstuvwxyz"
Output: true


👨‍💻 Алгоритм:

1⃣Создать словарь для хранения порядка каждой буквы в инопланетном языке.
Пройти по каждому слову и сравнить его с последующим словом.

2⃣Для каждого слова, сравнить буквы, используя созданный словарь порядка.
Если обнаружена пара слов, нарушающая порядок, вернуть false.

3⃣Если все слова отсортированы правильно, вернуть true.

😎 Решение:
var isAlienSorted = function(words, order) {
const orderMap = new Map();
for (let i = 0; i < order.length; i++) {
orderMap.set(order[i], i);
}

const compare = (word1, word2) => {
const minLength = Math.min(word1.length, word2.length);
for (let i = 0; i < minLength; i++) {
if (orderMap.get(word1[i]) < orderMap.get(word2[i])) {
return true;
} else if (orderMap.get(word1[i]) > orderMap.get(word2[i])) {
return false;
}
}
return word1.length <= word2.length;
};

for (let i = 0; i < words.length - 1; i++) {
if (!compare(words[i], words[i + 1])) {
return false;
}
}
return true;
};


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1249. Minimum Remove to Make Valid Parentheses
Сложность: medium

Дана строка s из '(' , ')' и строчных английских символов. Ваша задача - удалить минимальное количество скобок ( '(' или ')' в любых позициях), чтобы полученная строка со скобками была допустимой, и вернуть любую допустимую строку. Формально строка со скобками допустима тогда и только тогда, когда: она пустая, содержит только строчные символы, или может быть записана как AB (A, конкатенированная с B), где A и B - допустимые строки, или может быть записана как (A), где A - допустимая строка.

Пример:
Input: s = "lee(t(c)o)de)"
Output: "lee(t(c)o)de"


👨‍💻 Алгоритм:

1⃣Пройдите по строке s и сохраните индексы всех открывающих скобок '(' в стек. При встрече закрывающей скобки ')', удалите соответствующую открытую скобку из стека. Если в стеке нет соответствующей открывающей скобки, пометьте эту закрывающую скобку для удаления.

2⃣После первого прохода, все оставшиеся в стеке открывающие скобки пометьте для удаления.

3⃣Создайте новую строку, удалив все помеченные скобки.

😎 Решение:
var minRemoveToMakeValid = function(s) {
let stack = [];
s = s.split('');
for (let i = 0; i < s.length; i++) {
if (s[i] === '(') {
stack.push(i);
} else if (s[i] === ')') {
if (stack.length) {
stack.pop();
} else {
s[i] = '';
}
}
}
while (stack.length) {
s[stack.pop()] = '';
}
return s.join('');
};


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
💊3
Задача: 278. First Bad Version
Сложность: easy

Вы являетесь менеджером продукта и в настоящее время возглавляете команду по разработке нового продукта. К сожалению, последняя версия вашего продукта не прошла проверку качества. Поскольку каждая версия разрабатывается на основе предыдущей версии, все версии, вышедшие после плохой версии, также оказываются плохими.
Предположим, у вас есть n версий [1, 2, ..., n], и вы хотите выяснить первую плохую версию, которая вызывает все последующие версии быть плохими.
Вам предоставлен API bool isBadVersion(version), который возвращает, является ли версия плохой. Реализуйте функцию для нахождения первой плохой версии. Вы должны минимизировать количество вызовов API.

Пример:
Input: n = 5, bad = 4
Output: 4
Explanation:
call isBadVersion(3) -> false
call isBadVersion(5) -> true
call isBadVersion(4) -> true
Then 4 is the first bad version.


👨‍💻 Алгоритм:

1⃣Инициализация границ поиска:
Устанавливаем начальные значения левой и правой границ поиска: left = 1 и right = n.

2⃣Бинарный поиск:
Пока левая граница меньше правой, находим среднюю точку mid и проверяем, является ли она плохой версией с помощью isBadVersion(mid).
Если текущая версия mid плохая, смещаем правую границу к mid, иначе смещаем левую границу на mid + 1.

3⃣Возврат результата:
Когда левая граница станет равной правой, возвращаем left как индекс первой плохой версии.

😎 Решение:
var solution = function(isBadVersion) {
return function(n) {
let left = 1, right = n;
while (left < right) {
const mid = left + Math.floor((right - left) / 2);
if (isBadVersion(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
};
};


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 591. Tag Validator
Сложность: hard

Дана строка, представляющая фрагмент кода, реализуйте валидатор тегов для разбора кода и определения его корректности.
Фрагмент кода считается корректным, если соблюдаются все следующие правила:
Код должен быть заключен в корректный закрытый тег. В противном случае код некорректен.
Закрытый тег (не обязательно корректный) имеет точно следующий формат: <TAG_NAME>TAG_CONTENT</TAG_NAME>. Среди них <TAG_NAME> — это начальный тег, а </TAG_NAME> — конечный тег. TAG_NAME в начальном и конечном тегах должен быть одинаковым. Закрытый тег корректен, если и только если TAG_NAME и TAG_CONTENT корректны.
Корректное TAG_NAME содержит только заглавные буквы и имеет длину в диапазоне [1, 9]. В противном случае TAG_NAME некорректен.
Корректное TAG_CONTENT может содержать другие корректные закрытые теги, cdata и любые символы (см. примечание 1), КРОМЕ неподходящих <, неподходящих начальных и конечных тегов, и неподходящих или закрытых тегов с некорректным TAG_NAME. В противном случае TAG_CONTENT некорректен.
Начальный тег неподходящий, если нет конечного тега с тем же TAG_NAME, и наоборот. Однако нужно также учитывать проблему несбалансированных тегов, когда они вложены.
< неподходящий, если не удается найти последующий >. И когда вы находите < или </, все последующие символы до следующего > должны быть разобраны как TAG_NAME (не обязательно корректный).
cdata имеет следующий формат: <![CDATA[CDATA_CONTENT]]>. Диапазон CDATA_CONTENT определяется как символы между <![CDATA[ и первым последующим ]]>.
CDATA_CONTENT может содержать любые символы. Функция cdata заключается в том, чтобы запретить валидатору разбирать CDATA_CONTENT, поэтому даже если в нем есть символы, которые могут быть разобраны как тег (корректный или некорректный), вы должны рассматривать их как обычные символы.

Пример:
Input: code = "<DIV>This is the first line <![CDATA[<div>]]></DIV>"
Output: true


👨‍💻 Алгоритм:

1⃣Инициализируйте стек для отслеживания открытых тегов и флаг для определения наличия тегов. Используйте регулярное выражение для проверки корректности TAG_NAME, TAG_CONTENT и CDATA.

2⃣Пройдитесь по строке, проверяя каждый символ. Если встретите <, определите тип тега (начальный, конечный или CDATA). Обновите стек и индексы в зависимости от найденного типа.

3⃣В конце проверьте, что стек пуст (все теги корректно закрыты) и верните результат.

😎 Решение:
class Solution {
constructor() {
this.stack = [];
this.containsTag = false;
}

isValidTagName(s, ending) {
if (ending) {
if (this.stack.length > 0 && this.stack[this.stack.length - 1] === s) {
this.stack.pop();
} else {
return false;
}
} else {
this.containsTag = true;
this.stack.push(s);
}
return true;
}

isValid(code) {
const regex = /<[A-Z]{0,9}>([^<]*(<((\/?[A-Z]{1,9}>)|(!\[CDATA\[.*?\]\]>)))?)*/;
if (!regex.test(code)) {
return false;
}

for (let i = 0; i < code.length; i++) {
let ending = false;
if (this.stack.length === 0 && this.containsTag) {
return false;
}
if (code[i] === '<') {
if (code[i + 1] === '!') {
i = code.indexOf("]]>", i + 1);
if (i === -1) {
return false;
}
continue;
}
if (code[i + 1] === '/') {
i++;
ending = true;
}
const closeIndex = code.indexOf('>', i + 1);
if (closeIndex === -1 || !this.isValidTagName(code.slice(i + 1, closeIndex), ending)) {
return false;
}
i = closeIndex;
}
}
return this.stack.length === 0;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 336. Palindrome Pairs
Сложность: hard

Вам дан массив уникальных строк words, индексируемый с 0.
Пара палиндромов — это пара целых чисел (i, j), таких что:
0 <= i, j < words.length,
i != j, и
words[i] + words[j] (конкатенация двух строк) является палиндромом.
Верните массив всех пар палиндромов из слов.
Вы должны написать алгоритм с временной сложностью O(сумма длин всех слов в words).

Пример:
Input: words = ["abcd","dcba","lls","s","sssll"]
Output: [[0,1],[1,0],[3,2],[2,4]]
Explanation: The palindromes are ["abcddcba","dcbaabcd","slls","llssssll"]


👨‍💻 Алгоритм:

1⃣Инициализация и подготовка данных:
Создайте структуру для хранения результатов (список пар индексов).
Создайте словарь для хранения слов и их индексов, чтобы ускорить поиск.

2⃣Итерация по всем парам слов и проверка:
Пройдите по всем парам слов в массиве words, используя два вложенных цикла.
Для каждой пары слов проверяйте, образуют ли они палиндром при конкатенации. Это делается путем объединения строк и проверки, равна ли объединенная строка своей обратной версии.

3⃣Добавление найденных пар в результат:
Если проверка на палиндром проходит, добавьте текущую пару индексов в список результатов.
Верните итоговый список всех найденных пар.

😎 Решение:
var palindromePairs = function(words) {
let pairs = [];

for (let i = 0; i < words.length; i++) {
for (let j = 0; j < words.length; j++) {
if (i === j) continue;
let combined = words[i] + words[j];
if (combined === combined.split('').reverse().join('')) {
pairs.push([i, j]);
}
}
}

return pairs;
};


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM