Kotlin | LeetCode
1.84K subscribers
166 photos
1.1K links
Cайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp

Тесты t.iss.one/+Gzg9SH2MNxM0ZTYy
Вопросы соебсов t.iss.one/+OOb6zFa_-Oo3NjZi
Вакансии t.iss.one/+KuGNaHeKkQg1NzAy
Download Telegram
#medium
Задача: 250. Count Univalue Subtrees

Дан корень бинарного дерева, верните количество поддеревьев с одинаковыми значениями.

Поддерево с одинаковыми значениями означает, что все узлы поддерева имеют одно и то же значение.

Пример:
Input: root = [5,1,5,5,5,null,5]
Output: 4


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

1️⃣Создайте целочисленную переменную count для подсчета количества поддеревьев с одинаковыми значениями. Инициализируйте её значением 0.

2️⃣Выполните обход в глубину (DFS) для данного бинарного дерева. Выполните dfs(root), где dfs — это рекурсивный метод, который принимает узел TreeNode в качестве параметра, от которого начинается обход. Метод возвращает логическое значение, указывающее, является ли поддерево, укоренённое в этом узле, поддеревом с одинаковыми значениями. Выполните следующие действия в этом методе:
Если узел равен null, верните true.
Рекурсивно проверьте, образует ли левый потомок поддерево с одинаковыми значениями. Выполните isLeftUniValue = dfs(node.left).
Рекурсивно проверьте, образует ли правый потомок поддерево с одинаковыми значениями. Выполните isRightUniValue = dfs(node.right).
Если оба потомка образуют поддеревья с одинаковыми значениями, т.е. isLeftUniValue && isRightUniValue равно true, сравните значения потомков узла со значением самого узла. Если левый потомок существует и node.left.val != node.val, верните false, так как значения не совпадают и мы не имеем поддерева с одинаковыми значениями. Аналогично, если правый потомок существует и node.right.val != node.val, верните false. В противном случае, увеличьте count на 1 и верните true.
В противном случае, одно или оба поддерева потомков не образуют поддеревья с одинаковыми значениями, поэтому дерево, укоренённое в node, также не может быть таким поддеревом. Верните false.

3️⃣Верните count.

😎 Решение:
class TreeNode(var `val`: Int) {
var left: TreeNode? = null
var right: TreeNode? = null
}

class Solution {
private var count = 0

private fun dfs(node: TreeNode?): Boolean {
if (node == null) {
return true
}

val isLeftUniValue = dfs(node.left)
val isRightUniValue = dfs(node.right)

if (isLeftUniValue && isRightUniValue) {
if (node.left != null && node.left!!.`val` != node.`val`) {
return false
}
if (node.right != null && node.right!!.`val` != node.`val`) {
return false
}
count++
return true
}
return false
}

fun countUnivalSubtrees(root: TreeNode?): Int {
dfs(root)
return count
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
😁1
#medium
Задача: 267. Palindrome Permutation II

Дана строка s, верните все палиндромные перестановки (без дубликатов) этой строки.

Вы можете вернуть ответ в любом порядке. Если у строки s нет палиндромных перестановок, верните пустой список.

Пример:
Input: s = "aabb"
Output: ["abba","baab"]


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

1️⃣Проверка на возможность палиндромной перестановки:
Создаем хеш-таблицу, которая хранит количество вхождений каждого символа строки s.
Если количество символов с нечетным количеством вхождений превышает 1, то палиндромная перестановка
невозможна, и мы возвращаем пустой список.

2️⃣Генерация первой половины палиндромной строки:
Создаем строку st, которая содержит все символы строки s с количеством вхождений, уменьшенным до половины от их первоначального количества.
Если длина строки s нечетная, сохраняем символ, который встречается нечетное количество раз, отдельно.

3️⃣Генерация всех перестановок первой половины и создание палиндромов:
Генерируем все перестановки строки st.
Для каждой перестановки добавляем её обратную строку к самой себе, создавая тем самым полную палиндромную строку.
Если длина строки s нечетная, добавляем сохраненный символ в середину каждого палиндрома.
Чтобы избежать дубликатов, проверяем, равны ли элементы перед свапом. Если да, то пропускаем данную перестановку.

😎 Решение:
using System;
using System.Collections.Generic;
using System.Text;

public class Solution {
private HashSet<string> set;

public Solution() {
set = new HashSet<string>();
}

public IList<string> GeneratePalindromes(string s) {
int[] map = new int[128];
char[] st = new char[s.Length / 2];
if (!CanPermutePalindrome(s, map)) {
return new List<string>();
}

char ch = '\0';
int k = 0;
for (int i = 0; i < map.Length; i++) {
if (map[i] % 2 == 1) {
ch = (char)i;
}
for (int j = 0; j < map[i] / 2; j++) {
st[k++] = (char)i;
}
}
Permute(st, 0, ch);
return new List<string>(set);
}

private bool CanPermutePalindrome(string s, int[] map) {
int count = 0;
foreach (char c in s) {
int index = (int)c;
map[index]++;
if (map[index] % 2 == 0) {
count--;
} else {
count++;
}
}
return count <= 1;
}

private void Swap(ref char[] s, int i, int j) {
char temp = s[i];
s[i] = s[j];
s[j] = temp;
}

private void Permute(char[] s, int l, char ch) {
if (l == s.Length) {
StringBuilder sb = new StringBuilder();
sb.Append(s);
if (ch != '\0') {
sb.Append(ch);
}
Array.Reverse(s);
sb.Append(s);
set.Add(sb.ToString());
Array.Reverse(s);
} else {
for (int i = l; i < s.Length; i++) {
if (s[l] != s[i] || l == i) {
Swap(ref s, l, i);
Permute(s, l + 1, ch);
Swap(ref s, l, i);
}
}
}
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 267. Palindrome Permutation II

Дана строка s, верните все палиндромные перестановки (без дубликатов) этой строки.

Вы можете вернуть ответ в любом порядке. Если у строки s нет палиндромных перестановок, верните пустой список.

Пример:
Input: s = "aabb"
Output: ["abba","baab"]


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

1️⃣Проверка на возможность палиндромной перестановки:
Создаем хеш-таблицу для хранения количества вхождений каждого символа строки s.
Если количество символов с нечетным количеством вхождений превышает 1, возвращаем пустой список, так как палиндромная перестановка невозможна.

2️⃣Генерация палиндромных перестановок:
Создаем строку st, содержащую все символы строки s, но с количеством вхождений, уменьшенным до половины от их первоначального количества.
Если строка s имеет нечетную длину, один из символов должен встречаться нечетное количество раз. Этот символ ch сохраняем отдельно.

3️⃣Генерация всех перестановок строки st:
Для каждой перестановки строки st добавляем ее обратную строку, чтобы создать полную палиндромную строку.
Если строка s имеет нечетную длину, добавляем символ ch в середину каждой палиндромной перестановки.

4️⃣Исключение дубликатов:
Чтобы избежать создания дубликатов, перед выполнением свапа проверяем, равны ли элементы, которые будут поменяны местами. Если да, пропускаем эту перестановку.

😎 Решение:
class Solution {
private val set = HashSet<String>()

fun generatePalindromes(s: String): List<String> {
val map = IntArray(128)
val st = CharArray(s.length / 2)
if (!canPermutePalindrome(s, map)) {
return emptyList()
}

var ch = '\u0000'
var k = 0
for (i in map.indices) {
if (map[i] % 2 == 1) {
ch = i.toChar()
}
repeat(map[i] / 2) {
st[k++] = i.toChar()
}
}
permute(st, 0, ch)
return set.toList()
}

private fun canPermutePalindrome(s: String, map: IntArray): Boolean {
var count = 0
for (char in s) {
val index = char.toInt()
map[index]++
if (map[index] % 2 == 0) {
count--
} else {
count++
}
}
return count <= 1
}

private fun swap(s: CharArray, i: Int, j: Int) {
val temp = s[i]
s[i] = s[j]
s[j] = temp
}

private fun permute(s: CharArray, l: Int, ch: Char) {
if (l == s.size) {
val sb = StringBuilder()
sb.append(s)
if (ch != '\u0000') {
sb.append(ch)
}
sb.append(s.reversedArray())
set.add(sb.toString())
} else {
for (i in l until s.size) {
if (s[l] != s[i] || l == i) {
swap(s, l, i)
permute(s, l + 1, ch)
swap(s, l, i)
}
}
}
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 251. Flatten 2D Vector

Разработайте итератор для разворачивания двумерного вектора. Он должен поддерживать операции next и hasNext.

Реализуйте класс Vector2D:

Vector2D(int[][] vec) инициализирует объект двумерным вектором vec.
next() возвращает следующий элемент из двумерного вектора и перемещает указатель на один шаг вперед. Вы можете предположить, что все вызовы next допустимы.
hasNext() возвращает true, если в векторе еще остались элементы, и false в противном случае.

Пример:
Input
["Vector2D", "next", "next", "next", "hasNext", "hasNext", "next", "hasNext"]
[[[[1, 2], [3], [4]]], [], [], [], [], [], [], []]
Output
[null, 1, 2, 3, true, true, 4, false]

Explanation
Vector2D vector2D = new Vector2D([[1, 2], [3], [4]]);
vector2D.next(); // return 1
vector2D.next(); // return 2
vector2D.next(); // return 3
vector2D.hasNext(); // return True
vector2D.hasNext(); // return True
vector2D.next(); // return 4
vector2D.hasNext(); // return False


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

1️⃣Инициализация: Установите указатель position так, чтобы он указывал на следующий элемент массива, который должен быть возвращен методом next(). Это обеспечивает, что position всегда готов к получению следующего действительного элемента.

2️⃣Проверка доступности: Реализуйте метод hasNext(), который просто проверяет, находится ли индекс position в пределах допустимых индексов массива nums. Этот метод вернет true, если position указывает на действительный индекс, и false в противном случае.

3️⃣Получение следующего элемента: Метод next() возвращает элемент в текущей позиции position и продвигает указатель position на следующий индекс. Эта операция обеспечивает, что после вызова next(), position обновляется и указывает на следующий элемент, готовый к следующему вызову next().

😎 Решение:
class Vector2D(v: List<List<Int>>) {
private val nums: List<Int> = v.flatten()
private var position = -1

fun next(): Int {
position += 1
return nums[position]
}

fun hasNext(): Boolean {
return position + 1 < nums.size
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
#easy
Задача: 268. Missing Number

Дан массив nums, содержащий n различных чисел в диапазоне [0, n]. Верните единственное число в этом диапазоне, которого нет в массиве.

Пример:
Input: nums = [3,0,1]
Output: 2
Explanation: n = 3 since there are 3 numbers, so all numbers are in the range [0,3]. 2 is the missing number in the range since it does not appear in nums.


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

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

2️⃣Проверьте особые случаи: убедитесь, что число 0 находится в начале массива, а число n — в конце.

3️⃣Пройдитесь по отсортированному массиву и для каждого индекса проверьте, что число на этом индексе соответствует ожидаемому (предыдущее число плюс один). Как только вы обнаружите несоответствие, верните ожидаемое число.

😎 Решение:
class Solution {
fun missingNumber(nums: IntArray): Int {
nums.sort()
if (nums.last() != nums.size) {
return nums.size
} else if (nums.first() != 0) {
return 0
}
for (i in 1 until nums.size) {
val expectedNum = nums[i - 1] + 1
if (nums[i] != expectedNum) {
return expectedNum
}
}
return -1
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
😁1
#hard
Задача: 269. Alien Dictionary

Есть новый инопланетный язык, который использует английский алфавит. Однако порядок букв в нем неизвестен.

Вам дан список строк words из словаря инопланетного языка. Утверждается, что строки в words отсортированы лексикографически по правилам этого нового языка.

Если это утверждение неверно и данное расположение строк в words не может соответствовать никакому порядку букв, верните "".

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

Пример:
Input: words = ["wrt","wrf","er","ett","rftt"]
Output: "wertf"


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

1️⃣Извлечение отношений порядка и создание списков смежности:
Извлечь отношения порядка между буквами из слов.
Вставить их в список смежности, обрабатывая случаи, когда одно слово является префиксом другого.

2️⃣Подсчет числа входящих ребер:
Подсчитать количество входящих ребер (in-degree) для каждой буквы.
Построить исходящий список смежности и одновременно считать входящие ребра для каждой буквы.

3️⃣Обход в ширину (BFS):
Инициализировать очередь буквами с нулевым in-degree.
Выполнять BFS, добавляя буквы в результат, когда их in-degree становится нулевым.
Продолжать до тех пор, пока очередь не станет пустой.
Проверить наличие циклов и вернуть результат.

😎 Решение:
import java.util.*

class Solution {
fun alienOrder(words: Array<String>): String {
val adjList = mutableMapOf<Char, MutableSet<Char>>()
val inDegree = mutableMapOf<Char, Int>()

for (word in words) {
for (char in word) {
inDegree[char] = 0
}
}

for ((firstWord, secondWord) in words.zip(words.drop(1))) {
for ((c, d) in firstWord.zip(secondWord)) {
if (c != d) {
if (d !in adjList.getOrDefault(c, mutableSetOf())) {
adjList.getOrPut(c) { mutableSetOf() }.add(d)
inDegree[d] = inDegree.getOrDefault(d, 0) + 1
}
break
}
}
if (secondWord.length < firstWord.length && firstWord.startsWith(secondWord)) {
return ""
}
}

val output = mutableListOf<Char>()
val queue: Queue<Char> = LinkedList()

for ((char, degree) in inDegree) {
if (degree == 0) {
queue.add(char)
}
}

while (queue.isNotEmpty()) {
val c = queue.poll()
output.add(c)
for (d in adjList.getOrDefault(c, emptySet())) {
inDegree[d] = inDegree[d]!! - 1
if (inDegree[d] == 0) {
queue.add(d)
}
}
}

if (output.size < inDegree.size) {
return ""
}

return output.joinToString("")
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👀1
#easy
Задача: 270. Closest Binary Search Tree Value

Дано корень бинарного дерева поиска и целевое значение. Верните значение в дереве, которое ближе всего к целевому. Если существует несколько ответов, выведите наименьшее.

Пример:
Input: root = [4,2,5,1,3], target = 3.714286
Output: 4


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

1️⃣Построить массив с помощью inorder обхода:
Выполнить inorder обход дерева и собрать элементы в отсортированный массив.

2️⃣Найти ближайший элемент:
Пройти по массиву и определить элемент, наиболее близкий к целевому значению.

3️⃣Выбрать наименьший из ближайших элементов:
Если несколько элементов одинаково близки к целевому значению, выбрать наименьший из них.

😎 Решение:
class Solution {
fun closestValue(root: TreeNode?, target: Double): Int {
var closest = root?.`val` ?: 0
var node = root
while (node != null) {
if (Math.abs(node.`val` - target) < Math.abs(closest - target)) {
closest = node.`val`
} else if (Math.abs(node.`val` - target) == Math.abs(closest - target)) {
closest = minOf(node.`val`, closest)
}
node = if (target < node.`val`) node.left else node.right
}
return closest
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
😁1
#hard
Задача: 272. Closest Binary Search Tree Value II

Дано корень бинарного дерева поиска, целевое значение и целое число k. Верните k значений в дереве, которые ближе всего к целевому значению. Вы можете вернуть ответ в любом порядке.

Гарантируется, что в дереве есть только один уникальный набор из k значений, которые ближе всего к целевому значению.

Пример:
Input: root = [4,2,5,1,3], target = 3.714286, k = 2
Output: [4,3]


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

1️⃣Выполнить обход дерева в глубину (DFS) и собрать все значения в массив:
Пройти по дереву в глубину, добавляя каждое значение узла в массив.

2️⃣Отсортировать массив по расстоянию от целевого значения:
Использовать пользовательский компаратор, чтобы отсортировать массив по абсолютному значению разности между элементом массива и целевым значением.

3️⃣Вернуть первые k значений из отсортированного массива:
Извлечь первые k элементов из отсортированного массива и вернуть их.

😎 Решение:
class Solution {
fun closestKValues(root: TreeNode?, target: Double, k: Int): List<Int> {
val arr = mutableListOf<Int>()
dfs(root, arr)
arr.sortBy { Math.abs(it - target) }
return arr.take(k)
}

private fun dfs(node: TreeNode?, arr: MutableList<Int>) {
if (node == null) return
arr.add(node.`val`)
dfs(node.left, arr)
dfs(node.right, arr)
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 214. Shortest Palindrome

Дана строка s. Вы можете преобразовать s в палиндром, добавив символы в начало строки.

Верните самый короткий палиндром, который можно получить, выполняя это преобразование.

Пример:
Input: s = "aacecaaa"
Output: "aaacecaaa"


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

1️⃣ Создание обратной строки:
Создайте обратную строку rev от исходной строки s, чтобы использовать её для сравнения.

2️⃣ Итерация для поиска наибольшего палиндрома:
Перемещайтесь по индексу i от 0 до n - 1.
Для каждой итерации проверяйте, является ли подстрока s от начала до n - i равной подстроке rev от i до конца строки.
Если условие выполняется, это означает, что подстрока s от начала до n - i является палиндромом.
Возвращайте строку, состоящую из обратной подстроки rev от начала до i + исходная строка s.

3️⃣ Возврат результата:
Если не найдено совпадений, возвращайте пустую строку (хотя этот случай практически невозможен для непустой строки s).

😎 Решение:
class Solution {
fun shortestPalindrome(s: String): String {
val n = s.length
val rev = s.reversed()

for (i in 0 until n) {
if (s.substring(0, n - i) == rev.substring(i)) {
return rev.substring(0, i) + s
}
}

return ""
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 273. Integer to English Words

Преобразуйте неотрицательное целое число num в его словесное представление на английском языке.

Пример:
Input: num = 123
Output: "One Hundred Twenty Three"


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

1️⃣Обработка чисел до 20 и кратных 10 до 90:
Создать массивы или словари для чисел от 1 до 19 и для кратных 10 от 20 до 90.
Если число попадает в эти диапазоны, сразу вернуть соответствующее словесное представление.

2️⃣Обработка сотен, тысяч, миллионов и миллиардов:
Разделить число на группы по три цифры (единицы, тысячи, миллионы, миллиарды).
Для каждой группы сформировать словесное представление с использованием рекурсивной функции для чисел от 1 до 999.

3️⃣Формирование окончательного результата:
Собрать словесное представление всех групп, добавив соответствующие суффиксы (тысячи, миллионы, миллиарды).
Соединить все части в одну строку, удалив лишние пробелы.

😎 Решение:
class Solution {
private val belowTwenty = arrayOf("", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen")
private val tens = arrayOf("", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety")
private val thousands = arrayOf("", "Thousand", "Million", "Billion")

fun numberToWords(num: Int): String {
if (num == 0) return "Zero"
var num = num
var result = ""
var i = 0

while (num > 0) {
if (num % 1000 != 0) {
result = helper(num % 1000) + thousands[i] + " " + result
}
num /= 1000
i++
}
return result.trim()
}

private fun helper(num: Int): String {
if (num == 0) return ""
else if (num < 20) return belowTwenty[num] + " "
else if (num < 100) return tens[num / 10] + " " + helper(num % 10)
else return belowTwenty[num / 100] + " Hundred " + helper(num % 100)
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
#medium
Задача: 215. Kth Largest Element in an Array

Дан целочисленный массив nums и целое число k. Верните k-й наибольший элемент в массиве.

Обратите внимание, что это k-й наибольший элемент в отсортированном порядке, а не k-й уникальный элемент.

Пример:
Input: nums = [3,2,3,1,2,4,5,5,6], k = 4
Output: 4


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

1️⃣ Отсортируйте массив в порядке убывания:
Используйте стандартную функцию сортировки для сортировки элементов массива nums в порядке убывания. В этом случае самый большой элемент будет первым в массиве, второй по величине - вторым и так далее.

2️⃣ Найдите k-й по величине элемент:
После сортировки просто верните элемент, который стоит на позиции k-1 (учитывая, что индексация в массиве начинается с 0).

3️⃣ Верните результат:
Возвратите найденное значение как результат.

😎 Решение:
class Solution {
fun shortestPalindrome(s: String): String {
val n = s.length
val rev = s.reversed()
for (i in 0 until n) {
if (s.substring(0, n - i) == rev.substring(i)) {
return rev.substring(0, i) + s
}
}
return ""
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
#medium
Задача: 216. Combination Sum III

Найдите все допустимые комбинации k чисел, которые в сумме дают n, при условии, что:

Используются только числа от 1 до 9.
Каждое число используется не более одного раза.
Верните список всех возможных допустимых комбинаций. Список не должен содержать одинаковые комбинации, и комбинации могут возвращаться в любом порядке.

Пример:
Input: k = 3, n = 9
Output: [[1,2,6],[1,3,5],[2,3,4]]
Explanation:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
There are no other valid combinations.


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

1️⃣ Инициализация и запуск рекурсивной функции:
Создайте вспомогательную функцию backtrack, которая принимает текущую оставшуюся сумму, размер комбинации k, текущую комбинацию, индекс следующего элемента для добавления и список результатов.
Инициализируйте пустые векторы для хранения текущей комбинации и всех возможных результатов.
Запустите функцию backtrack с начальными значениями: полной суммой n, размером комбинации k, пустой комбинацией, начальным индексом 0 и пустым списком результатов.

2️⃣ Рекурсивная обработка:
В функции backtrack проверьте, если текущая сумма равна нулю и размер комбинации равен k, добавьте копию текущей комбинации в список результатов.
Если текущая сумма меньше нуля или размер комбинации равен k, прекратите текущую ветвь обработки.
Иначе, итерируйтесь по оставшимся кандидатам, начиная с текущего индекса. Для каждого кандидата добавьте его в текущую комбинацию, обновите оставшуюся сумму и вызовите backtrack с обновленными параметрами. После возвращения из рекурсивного вызова удалите последний элемент из комбинации для рассмотрения следующего кандидата.

3️⃣ Возвращение результатов:
По завершении всех рекурсивных вызовов функция combinationSum3 возвращает список всех найденных комбинаций.

😎 Решение:
class Solution {
fun backtrack(remain: Int, k: Int, comb: MutableList<Int>, nextStart: Int, results: MutableList<MutableList<Int>>) {
if (remain == 0 && comb.size == k) {
results.add(ArrayList(comb))
return
} else if (remain < 0 || comb.size == k) {
return
}

for (i in nextStart until 9) {
comb.add(i + 1)
backtrack(remain - i - 1, k, comb, i + 1, results)
comb.removeAt(comb.size - 1)
}
}

fun combinationSum3(k: Int, n: Int): List<List<Int>> {
val results = mutableListOf<MutableList<Int>>()
val comb = mutableListOf<Int>()
backtrack(n, k, comb, 0, results)
return results
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 274. H-Index

Дан массив целых чисел citations, где citations[i] — количество цитирований, которое исследователь получил за свою i-ю статью. Верните h-индекс исследователя.
Согласно определению h-индекса на Википедии: h-индекс определяется как максимальное значение h, такое что данный исследователь опубликовал по крайней мере h статей, каждая из которых была процитирована как минимум h раз.

Пример:
Input: citations = [3,0,6,1,5]
Output: 3
Explanation: [3,0,6,1,5] means the researcher has 5 papers in total and each of them had received 3, 0, 6, 1, 5 citations respectively.
Since the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, their h-index is 3.


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

1️⃣Отсортировать массив цитирований по убыванию:
Отсортировать массив citations в порядке убывания, чтобы наибольшее количество цитирований было в начале массива.

2️⃣Найти наибольшее значение i, для которого citations[i] > i:
Пройтись по отсортированному массиву и найти наибольшее значение i, для которого выполняется условие citations[i] > i.
Это значение будет индексом, при котором количество цитирований статьи больше индекса.

3️⃣Рассчитать h-индекс:
h-индекс будет равен i + 1, где i - наибольшее значение, найденное на предыдущем шаге.

😎 Решение:
class Solution {
fun hIndex(citations: IntArray): Int {
val n = citations.size
val papers = IntArray(n + 1)
for (c in citations) {
papers[Math.min(n, c)]++
}
var k = n
var s = papers[n]
while (k > s) {
k--
s += papers[k]
}
return k
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
💊2
#medium
Задача: 275. H-Index II

Дан массив целых чисел citations, где citations[i] — количество цитирований, которое исследователь получил за свою i-ю статью, и массив отсортирован в порядке возрастания. Верните h-индекс исследователя.
Согласно определению h-индекса на Википедии: h-индекс определяется как максимальное значение h, такое что данный исследователь опубликовал по крайней мере h статей, каждая из которых была процитирована как минимум h раз.
Вы должны написать алгоритм, который работает за логарифмическое время.

Пример:
Input: citations = [0,1,3,5,6]
Output: 3
Explanation: [0,1,3,5,6] means the researcher has 5 papers in total and each of them had received 0, 1, 3, 5, 6 citations respectively.
Since the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, their h-index is 3.


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

1️⃣Найти середину массива:
Определить средний элемент массива, чтобы разделить его на две подмножества: citations[0: mid - 1] и citations[mid + 1: n].

2️⃣Сравнить количество статей с цитированиями больше или равными citations[mid]:
Если citations[mid] == n - mid, то найден h-индекс и его можно вернуть.
Если citations[mid] < n - mid, то необходимо искать в правой подмножности citations[mid + 1: n].
Если citations[mid] > n - mid, то необходимо искать в левой подмножности citations[0: mid - 1].

3️⃣Возвращение результата:
Продолжать процесс, пока не будет найден h-индекс.
Возвратить n - mid, что является количеством статей с цитированиями больше или равными citations[mid].

😎 Решение:
class Solution {
fun hIndex(citations: IntArray): Int {
val n = citations.size
var left = 0
var right = n - 1

while (left <= right) {
val mid = left + (right - left) / 2
if (citations[mid] == n - mid) {
return n - mid
} else if (citations[mid] < n - mid) {
left = mid + 1
} else {
right = mid - 1
}
}
return n - left
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3👀1
#easy
Задача: 217. Contains Duplicate

Дан массив целых чисел nums. Верните true, если любое значение появляется в массиве хотя бы дважды, и верните false, если каждый элемент уникален.

Пример:
Input: nums = [1,2,3,4]
Output: false


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

1️⃣ Отсортируйте массив nums по возрастанию.

2️⃣ Итерируйте по отсортированному массиву и сравнивайте каждое число с следующим.

3️⃣ Если любое число совпадает с следующим, верните true. Если цикл завершится без совпадений, верните false.

😎 Решение:
fun containsDuplicate(nums: IntArray): Boolean {
nums.sort()
for (i in 0 until nums.size - 1) {
if (nums[i] == nums[i + 1]) {
return true
}
}
return false
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1💊1
#hard
Задача: 218. The Skyline Problem

Горизонт города — это внешний контур силуэта, образованного всеми зданиями в этом городе, когда они видны издалека. Учитывая расположения и высоты всех зданий, верните горизонт, образованный этими зданиями в совокупности.

Геометрическая информация о каждом здании задана в массиве buildings, где buildings[i] = [lefti, righti, heighti]:

lefti — это координата x левого края i-го здания.
righti — это координата x правого края i-го здания.
heighti — это высота i-го здания.
Вы можете предположить, что все здания — это идеальные прямоугольники, стоящие на абсолютно плоской поверхности на высоте 0.

Пример:
Input: buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
Output: [[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
Explanation:
Figure A shows the buildings of the input.
Figure B shows the skyline formed by those buildings. The red points in figure B represent the key points in the output list.


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

1️⃣ Соберите все уникальные позиции для левых и правых краев зданий в массиве buildings и сохраните их в список edgeSet. Инициализируйте хэш-таблицу edgeIndexMap для хранения соответствующих индексов и значений элементов из heights.

2️⃣ Пройдитесь по всем зданиям в массиве buildings, найдите индексы их левого и правого краев, а также их высоту. Для каждого здания обновите максимальную высоту в диапазоне [leftIndex, rightIndex).

3️⃣ Пройдитесь по обновленным высотам и добавьте все позиции, где высота меняется, в answer в качестве ключевых точек горизонта. Верните answer как результат.

😎 Решение:
class Solution {
fun getSkyline(buildings: Array<IntArray>): List<List<Int>> {
val edgeSet = TreeSet<Int>()
for (building in buildings) {
edgeSet.add(building[0])
edgeSet.add(building[1])
}
val edges = edgeSet.toList()
val edgeIndexMap = mutableMapOf<Int, Int>()
for (i in edges.indices) {
edgeIndexMap[edges[i]] = i
}
val heights = IntArray(edges.size)
for (building in buildings) {
val left = building[0]
val right = building[1]
val height = building[2]
val leftIndex = edgeIndexMap[left]!!
val rightIndex = edgeIndexMap[right]!!
for (idx in leftIndex until rightIndex) {
heights[idx] = maxOf(heights[idx], height)
}
}
val answer = mutableListOf<List<Int>>()
for (i in heights.indices) {
val currHeight = heights[i]
val currPos = edges[i]
if (answer.isEmpty() || answer.last()[1] != currHeight) {
answer.add(listOf(currPos, currHeight))
}
}
return answer
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🤯1
#medium
Задача: 276. Paint Fence

Вы красите забор из n столбцов, используя k различных цветов. Вы должны красить столбы, следуя этим правилам:
Каждый столб должен быть окрашен в один цвет.
Не может быть трех или более подряд идущих столбцов одного цвета.
Учитывая два целых числа n и k, верните количество способов покрасить забор.

Пример:
Input: n = 3, k = 2
Output: 6
Explanation: All the possibilities are shown.
Note that painting all the posts red or all the posts green is invalid because there cannot be three posts in a row with the same color.


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

1️⃣Инициализация и определение вспомогательной функции:
Определить хеш-таблицу memo, где memo[i] представляет количество способов покрасить i столбцов.
Определить функцию totalWays, которая будет определять количество способов покрасить i столбцов.

2️⃣Реализация базы и проверка кэша:
В функции totalWays проверить базовые случаи: вернуть k, если i == 1, и вернуть k * k, если i == 2.
Проверить, рассчитан ли аргумент i и сохранен ли в memo. Если да, вернуть memo[i].

3️⃣Расчет с использованием рекуррентного соотношения:
В противном случае использовать рекуррентное соотношение для вычисления memo[i], сохранить результат в memo[i] и вернуть его.
Вызвать и вернуть totalWays(n).

😎 Решение:
class Solution {
fun numWays(n: Int, k: Int): Int {
if (n == 1) return k

var twoPostsBack = k
var onePostBack = k * k

for (i in 3..n) {
val curr = (k - 1) * (onePostBack + twoPostsBack)
twoPostsBack = onePostBack
onePostBack = curr
}

return onePostBack
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
😁1
#easy
Задача: 219. Contains Duplicate II

Дан массив целых чисел nums и целое число k. Верните true, если в массиве существуют два различных индекса i и j, такие что nums[i] == nums[j] и abs(i - j) <= k.

Пример:
Input: nums = [1,2,3,1,2,3], k = 2
Output: false


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

1️⃣ Создайте пустое множество set.

2️⃣ Пройдитесь по массиву nums:
Если текущий элемент уже есть в множестве, верните true.
Добавьте текущий элемент в множество.
Если размер множества больше k, удалите элемент, который был добавлен k шагов назад.

3️⃣ Если не найдены дублирующиеся элементы на расстоянии k или менее, верните false.

😎 Решение:
class Solution {
fun containsNearbyDuplicate(nums: IntArray, k: Int): Boolean {
val set = mutableSetOf<Int>()
for (i in nums.indices) {
if (set.contains(nums[i])) return true
set.add(nums[i])
if (set.size > k) set.remove(nums[i - k])
}
return false
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
#medium
Задача: 314. Binary Tree Vertical Order Traversal

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

Если два узла находятся в одной строке и столбце, порядок должен быть слева направо.

Пример:
Input: root = [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]


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

1️⃣Создайте хэш-таблицу с именем columnTable для отслеживания результатов.

2️⃣Инициализируйте очередь, поместив в нее корневой узел вместе с его индексом столбца (0). Выполните обход в ширину (BFS), извлекая элементы из очереди. На каждой итерации извлекайте элемент, состоящий из узла и соответствующего индекса столбца. Если узел не пуст, добавьте его значение в columnTable. Затем поместите дочерние узлы с их индексами столбцов (т.е. column-1 и column+1) в очередь.

3️⃣После завершения BFS обхода получите хэш-таблицу, содержащую значения узлов, сгруппированные по индексам столбцов. Для каждой группы значений отсортируйте их по индексам строк. Отсортируйте хэш-таблицу по ключам (индексам столбцов) в порядке возрастания и верните результаты по столбцам.

😎 Решение:
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap

class TreeNode(var `val`: Int) {
var left: TreeNode? = null
var right: TreeNode? = null
}

class Solution {
fun verticalOrder(root: TreeNode?): List<List<Int>> {
val columnTable = HashMap<Int, MutableList<Int>>()
val queue: Queue<Pair<TreeNode?, Int>> = LinkedList()
queue.add(Pair(root, 0))

while (queue.isNotEmpty()) {
val (node, column) = queue.poll()

if (node != null) {
if (!columnTable.containsKey(column)) {
columnTable[column] = ArrayList()
}
columnTable[column]?.add(node.`val`)

queue.add(Pair(node.left, column - 1))
queue.add(Pair(node.right, column + 1))
}
}

return columnTable.keys.sorted().map { columnTable[it] ?: emptyList() }
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
😁1
#hard
Задача: 315. Count of Smaller Numbers After Self

Дан целочисленный массив nums, верните целочисленный массив counts, где counts[i] - это количество элементов справа от nums[i], которые меньше nums[i].

Пример:
Input: nums = [5,2,6,1]
Output: [2,1,1,0]
Explanation:
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.


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

1️⃣Реализуйте дерево отрезков (segment tree). Поскольку дерево инициализируется нулями, нужно реализовать только операции обновления и запроса. Установите смещение offset = 10^4.

2️⃣Итерация по каждому числу в nums в обратном порядке. Для каждого числа выполните следующие действия:
Смещайте число на num + offset.
Запросите количество элементов в дереве отрезков, которые меньше текущего числа.
Обновите счетчик текущего числа в дереве отрезков.

3️⃣Верните результат.

😎 Решение:
class Solution {
fun countSmaller(nums: IntArray): List<Int> {
fun update(index: Int, value: Int, tree: IntArray, size: Int) {
var idx = index + size
tree[idx] += value
while (idx > 1) {
idx /= 2
tree[idx] = tree[idx * 2] + tree[idx * 2 + 1]
}
}

fun query(left: Int, right: Int, tree: IntArray, size: Int): Int {
var result = 0
var l = left + size
var r = right + size
while (l < r) {
if (l % 2 == 1) {
result += tree[l]
l++
}
l /= 2
if (r % 2 == 1) {
r--
result += tree[r]
}
r /= 2
}
return result
}

val offset = 10000
val size = 2 * 10000 + 1
val tree = IntArray(2 * size)
val result = mutableListOf<Int>()
for (num in nums.reversed()) {
val smallerCount = query(0, num + offset, tree, size)
result.add(smallerCount)
update(num + offset, 1, tree, size)
}
return result.reversed()
}
}


🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM