Задача: 243. Shortest Word Distance
Сложность: easy
Дан массив строк
Пример:
👨💻 Алгоритм:
1⃣ Начните с перебора всего массива для поиска первого слова. Каждый раз, когда вы находите встречу первого слова, запомните его позицию.
2⃣ При каждом обнаружении первого слова переберите массив в поисках ближайшего вхождения второго слова, сохраняя позицию и сравнивая расстояние с предыдущими найденными.
3⃣ Сохраняйте минимальное найденное расстояние между двумя словами и возвращайте его в качестве результата.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив строк
wordsDict и две разные строки, которые уже существуют в массиве: word1 и word2. Верните кратчайшее расстояние между этими двумя словами в списке.Пример:
Input: wordsDict = ["practice", "makes", "perfect", "coding", "makes"], word1 = "coding", word2 = "practice"
Output: 3
type Solution struct{}
func (s *Solution) ShortestDistance(words []string, word1 string, word2 string) int {
minDistance := len(words)
for i, w1 := range words {
if w1 == word1 {
for j, w2 := range words {
if w2 == word2 {
if diff := abs(i - j); diff < minDistance {
minDistance = diff
}
}
}
}
}
return minDistance
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 972. Equal Rational Numbers
Сложность: hard
Даны две строки s и t, каждая из которых представляет собой неотрицательное рациональное число. Вернуть true тогда и только тогда, когда они представляют одно и то же число. Строки могут использовать скобки для обозначения повторяющейся части рационального числа.
Рациональное число может быть представлено с использованием до трех частей: <ЦелаяЧасть>, <НеповторяющаясяЧасть> и <ПовторяющаясяЧасть>. Число будет представлено одним из следующих трех способов:
<ЦелаяЧасть>
Например, 12, 0 и 123.
<ЦелаяЧасть><.><НеповторяющаясяЧасть>
Например, 0.5, 1., 2.12 и 123.0001.
<ЦелаяЧасть><.><НеповторяющаясяЧасть><(><ПовторяющаясяЧасть><)>
Например, 0.1(6), 1.(9), 123.00(1212).
Повторяющаяся часть десятичного разложения обозначается в круглых скобках. Например:
1/6 = 0.16666666... = 0.1(6) = 0.1666(6) = 0.166(66).
Пример:
👨💻 Алгоритм:
1⃣ Преобразование дроби. Определите и изолируйте повторяющуюся часть дроби. Преобразуйте строку, представляющую число, в выражение вида S=x/(10^k-1), где x — повторяющаяся часть, а k — её длина.
2⃣ Вычисление геометрической суммы. Преобразуйте повторяющуюся часть в сумму вида S=x*(r/(1-r)), где r = 10^(-k). Найдите значение дроби для повторяющейся части, используя формулу геометрической прогрессии.
3⃣ Обработка неповторяющейся части. Определите значение неповторяющейся части дроби как обычное число. Объедините результаты для повторяющейся и неповторяющейся частей для получения итогового значения.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Даны две строки s и t, каждая из которых представляет собой неотрицательное рациональное число. Вернуть true тогда и только тогда, когда они представляют одно и то же число. Строки могут использовать скобки для обозначения повторяющейся части рационального числа.
Рациональное число может быть представлено с использованием до трех частей: <ЦелаяЧасть>, <НеповторяющаясяЧасть> и <ПовторяющаясяЧасть>. Число будет представлено одним из следующих трех способов:
<ЦелаяЧасть>
Например, 12, 0 и 123.
<ЦелаяЧасть><.><НеповторяющаясяЧасть>
Например, 0.5, 1., 2.12 и 123.0001.
<ЦелаяЧасть><.><НеповторяющаясяЧасть><(><ПовторяющаясяЧасть><)>
Например, 0.1(6), 1.(9), 123.00(1212).
Повторяющаяся часть десятичного разложения обозначается в круглых скобках. Например:
1/6 = 0.16666666... = 0.1(6) = 0.1666(6) = 0.166(66).
Пример:
Input: s = "0.(52)", t = "0.5(25)"
Output: true
Explanation: Because "0.(52)" represents 0.52525252..., and "0.5(25)" represents 0.52525252525..... , the strings represent the same number.
package main
import (
"math"
"strconv"
"strings"
)
type Fraction struct {
n, d int64
}
func (f *Fraction) iadd(other Fraction) {
numerator := f.n*other.d + f.d*other.n
denominator := f.d * other.d
g := gcd(numerator, denominator)
f.n = numerator / g
f.d = denominator / g
}
func gcd(x, y int64) int64 {
if x != 0 {
return gcd(y%x, x)
}
return y
}
func isRationalEqual(S string, T string) bool {
f1 := convert(S)
f2 := convert(T)
return f1.n == f2.n && f1.d == f2.d
}
func convert(S string) Fraction {
state := 0
ans := Fraction{0, 1}
decimalSize := 0
parts := strings.FieldsFunc(S, func(r rune) bool {
return r == '.' || r == '(' || r == ')'
})
for _, part := range parts {
state++
if part == "" {
continue
}
x, _ := strconv.ParseInt(part, 10, 64)
sz := len(part)
if state == 1 {
ans.iadd(Fraction{x, 1})
} else if state == 2 {
ans.iadd(Fraction{x, int64(math.Pow(10, float64(sz)))})
decimalSize = sz
} else {
denom := int64(math.Pow(10, float64(decimalSize)))
denom *= int64(math.Pow(10, float64(sz)) - 1)
ans.iadd(Fraction{x, denom})
}
}
return ans
}
func main() {
// Test the function here
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 934. Shortest Bridge
Сложность: medium
Вам дана двоичная матричная сетка n x n, где 1 обозначает сушу, а 0 - воду. Остров - это 4-направленно связанная группа из 1, не соединенная ни с одной другой 1. В сетке ровно два острова. Вы можете поменять 0 на 1, чтобы соединить два острова в один. Верните наименьшее количество 0, которое нужно перевернуть, чтобы соединить два острова.
Пример:
👨💻 Алгоритм:
1⃣ Найти все клетки, принадлежащие первому острову, используя DFS/BFS, и добавить их в очередь для последующего расширения.
2⃣ Использовать BFS для расширения из каждой клетки первого острова, чтобы найти кратчайший путь к клетке второго острова.
3⃣ Вернуть длину кратчайшего пути.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дана двоичная матричная сетка n x n, где 1 обозначает сушу, а 0 - воду. Остров - это 4-направленно связанная группа из 1, не соединенная ни с одной другой 1. В сетке ровно два острова. Вы можете поменять 0 на 1, чтобы соединить два острова в один. Верните наименьшее количество 0, которое нужно перевернуть, чтобы соединить два острова.
Пример:
Input: grid = [[0,1],[1,0]]
Output: 1
package main
type Pair struct {
x, y int
}
func shortestBridge(grid [][]int) int {
n := len(grid)
directions := [][]int{
{-1, 0},
{1, 0},
{0, -1},
{0, 1},
}
queue := []Pair{}
found := false
var dfs func(x, y int)
dfs = func(x, y int) {
if x < 0 || x >= n || y < 0 || y >= n || grid[x][y] != 1 {
return
}
grid[x][y] = -1
queue = append(queue, Pair{x, y})
for _, dir := range directions {
nx, ny := x+dir[0], y+dir[1]
dfs(nx, ny)
}
}
for i := 0; i < n && !found; i++ {
for j := 0; j < n && !found; j++ {
if grid[i][j] == 1 {
dfs(i, j)
found = true
}
}
}
steps := 0
for len(queue) > 0 {
size := len(queue)
for i := 0; i < size; i++ {
p := queue[0]
queue = queue[1:]
for _, dir := range directions {
nx, ny := p.x+dir[0], p.y+dir[1]
if nx >= 0 && nx < n && ny >= 0 && ny < n {
if grid[nx][ny] == 1 {
return steps
}
if grid[nx][ny] == 0 {
grid[nx][ny] = -1
queue = append(queue, Pair{nx, ny})
}
}
}
}
steps++
}
return -1
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 559. Maximum Depth of N-ary Tree
Сложность: easy
Дано n-арное дерево, найдите его максимальную глубину.
Максимальная глубина - это количество узлов вдоль самого длинного пути от корневого узла до самого дальнего листового узла.
Сериализация ввода n-арного дерева представлена в порядке уровня, каждая группа дочерних узлов разделена значением null (см. примеры).
Пример:
👨💻 Алгоритм:
1⃣ Интуитивный подход заключается в решении задачи с помощью рекурсии.
2⃣ Здесь мы демонстрируем пример с использованием стратегии поиска в глубину (DFS - Depth First Search).
3⃣ Применяя DFS, проходим через все узлы дерева, вычисляя максимальную глубину.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дано n-арное дерево, найдите его максимальную глубину.
Максимальная глубина - это количество узлов вдоль самого длинного пути от корневого узла до самого дальнего листового узла.
Сериализация ввода n-арного дерева представлена в порядке уровня, каждая группа дочерних узлов разделена значением null (см. примеры).
Пример:
Input: root = [1,null,3,2,4,null,5,6]
Output: 3
type Node struct {
Val int
Children []*Node
}
func maxDepth(root *Node) int {
if root == nil {
return 0
} else if len(root.Children) == 0 {
return 1
} else {
heights := []int{}
for _, child := range root.Children {
heights = append(heights, maxDepth(child))
}
max := 0
for _, h := range heights {
if h > max {
max = h
}
}
return max + 1
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Задача: 1011. Capacity To Ship Packages Within D Days
Сложность: medium
На конвейерной ленте находятся пакеты, которые должны быть отправлены из одного порта в другой в течение нескольких дней. i-й пакет на конвейерной ленте имеет массу weights[i]. Каждый день мы загружаем корабль пакетами на конвейерной ленте (в порядке, заданном весами). Мы не можем загрузить больше груза, чем максимальная грузоподъемность корабля. Верните наименьшую грузоподъемность корабля, при которой все посылки на конвейере будут отправлены в течение нескольких дней.
Пример:
👨💻 Алгоритм:
1⃣ Определение диапазона возможных ответов:
Минимальная грузоподъемность должна быть не меньше максимального веса одного пакета (чтобы хотя бы один пакет можно было загрузить).
Максимальная грузоподъемность - это сумма всех весов (если все пакеты будут отправлены за один день).
2⃣ Использование бинарного поиска:
Примените бинарный поиск в диапазоне от минимальной до максимальной грузоподъемности, чтобы найти наименьшую грузоподъемность, при которой все пакеты можно отправить за заданное количество дней.
3⃣ Проверка возможности отправки всех пакетов за заданное количество дней:
Напишите вспомогательную функцию, которая проверяет, можно ли отправить все пакеты при заданной грузоподъемности за определенное количество дней. Эта функция проходит по списку весов и считает количество необходимых дней для отправки всех пакетов при текущей грузоподъемности.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
На конвейерной ленте находятся пакеты, которые должны быть отправлены из одного порта в другой в течение нескольких дней. i-й пакет на конвейерной ленте имеет массу weights[i]. Каждый день мы загружаем корабль пакетами на конвейерной ленте (в порядке, заданном весами). Мы не можем загрузить больше груза, чем максимальная грузоподъемность корабля. Верните наименьшую грузоподъемность корабля, при которой все посылки на конвейере будут отправлены в течение нескольких дней.
Пример:
Input: weights = [1,2,3,4,5,6,7,8,9,10], days = 5
Output: 15
Минимальная грузоподъемность должна быть не меньше максимального веса одного пакета (чтобы хотя бы один пакет можно было загрузить).
Максимальная грузоподъемность - это сумма всех весов (если все пакеты будут отправлены за один день).
Примените бинарный поиск в диапазоне от минимальной до максимальной грузоподъемности, чтобы найти наименьшую грузоподъемность, при которой все пакеты можно отправить за заданное количество дней.
Напишите вспомогательную функцию, которая проверяет, можно ли отправить все пакеты при заданной грузоподъемности за определенное количество дней. Эта функция проходит по списку весов и считает количество необходимых дней для отправки всех пакетов при текущей грузоподъемности.
func shipWithinDays(weights []int, D int) int {
canShipInDays := func(capacity int) bool {
days := 1
total := 0
for _, weight := range weights {
if total+weight > capacity {
days++
total = 0
}
total += weight
}
return days <= D
}
left, right := max(weights), sum(weights)
for left < right {
mid := (left + right) / 2
if canShipInDays(mid) {
right = mid
} else {
left = mid + 1
}
}
return left
}
func max(arr []int) int {
maxVal := arr[0]
for _, v := range arr {
if v > maxVal {
maxVal = v
}
}
return maxVal
}
func sum(arr []int) int {
total := 0
for _, v := range arr {
total += v
}
return total
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1315. Sum of Nodes with Even-Valued Grandparent
Сложность: medium
Given the root of a binary tree, return the sum of values of nodes with an even-valued grandparent. If there are no nodes with an even-valued grandparent, return 0.
A grandparent of a node is the parent of its parent if it exists.
Пример:
👨💻 Алгоритм:
1⃣ Определите метод solve(), который принимает TreeNode root, значение родителя parent и значение бабушки или дедушки gParent. Этот метод возвращает сумму значений узлов с четным значением бабушки и дедушки в поддереве узла root. Если root равен null, верните 0 как сумму.
2⃣ Рекурсивно пройдите по левому и правому дочерним узлам, передавая в качестве значения parent root, а в качестве значения gParent parent. Если значение gParent четное, добавьте значение root к ответу.
3⃣ Вызовите рекурсивную функцию solve() с корневым узлом и значениями -1 для parent и gParent. Верните сумму для левого и правого дочерних узлов и значение для текущего узла.
😎 Решение
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Given the root of a binary tree, return the sum of values of nodes with an even-valued grandparent. If there are no nodes with an even-valued grandparent, return 0.
A grandparent of a node is the parent of its parent if it exists.
Пример:
Input: root = [6,7,8,2,7,1,3,9,null,1,4,null,null,null,5]
Output: 18
Explanation: The red nodes are the nodes with even-value grandparent while the blue nodes are the even-value grandparents.
func solve(root *TreeNode, parent, gParent int) int {
if root == nil {
return 0
}
return solve(root.Left, root.Val, parent) + solve(root.Right, root.Val, parent) + func() int {
if gParent%2 == 0 {
return root.Val
}
return 0
}()
}
func sumEvenGrandparent(root *TreeNode) int {
return solve(root, -1, -1)
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔2
Задача: 685. Redundant Connection II
Сложность: hard
В этой задаче корневое дерево — это направленный граф, в котором существует ровно один узел (корень), для которого все остальные узлы являются потомками этого узла, плюс каждый узел имеет ровно одного родителя, за исключением корневого узла, у которого нет родителей.
Данный ввод представляет собой направленный граф, который изначально был корневым деревом с n узлами (со значениями от 1 до n), и к которому добавлено одно дополнительное направленное ребро. Добавленное ребро соединяет две разные вершины, выбранные из 1 до n, и это ребро не существовало ранее.
Результирующий граф представлен в виде двумерного массива ребер. Каждый элемент массива edges — это пара [ui, vi], представляющая направленное ребро, соединяющее узлы ui и vi, где ui является родителем ребенка vi.
Верните ребро, которое можно удалить, чтобы результирующий граф стал корневым деревом с n узлами. Если существует несколько ответов, верните ответ, который встречается последним в данном двумерном массиве.
Пример:
👨💻 Алгоритм:
1⃣ Сначала создаем базовый граф, отслеживая ребра, идущие от узлов с несколькими родителями. В итоге у нас будет либо 2, либо 0 кандидатов на удаление ребра.
2⃣ Если кандидатов нет, то каждый узел имеет одного родителя, как в случае 1->2->3->4->1->5. От любого узла идем к его родителю, пока не посетим узел повторно — тогда мы окажемся внутри цикла, и любые последующие посещенные узлы будут частью этого цикла. В этом случае удаляем последнее ребро, входящее в цикл.
3⃣ Если есть кандидаты, проверяем, является ли граф, созданный из родителей, корневым деревом. Идем от любого узла к его родителю, пока это возможно, затем выполняем обход в глубину (DFS) от этого корня. Если посещаем каждый узел, удаление последнего из двух кандидатов приемлемо. В противном случае удаляем первое из двух ребер-кандидатов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
В этой задаче корневое дерево — это направленный граф, в котором существует ровно один узел (корень), для которого все остальные узлы являются потомками этого узла, плюс каждый узел имеет ровно одного родителя, за исключением корневого узла, у которого нет родителей.
Данный ввод представляет собой направленный граф, который изначально был корневым деревом с n узлами (со значениями от 1 до n), и к которому добавлено одно дополнительное направленное ребро. Добавленное ребро соединяет две разные вершины, выбранные из 1 до n, и это ребро не существовало ранее.
Результирующий граф представлен в виде двумерного массива ребер. Каждый элемент массива edges — это пара [ui, vi], представляющая направленное ребро, соединяющее узлы ui и vi, где ui является родителем ребенка vi.
Верните ребро, которое можно удалить, чтобы результирующий граф стал корневым деревом с n узлами. Если существует несколько ответов, верните ответ, который встречается последним в данном двумерном массиве.
Пример:
Input: edges = [[1,2],[1,3],[2,3]]
Output: [2,3]
package main
type Solution struct{}
func (s *Solution) findRedundantDirectedConnection(edges [][]int) []int {
N := len(edges)
parent := make(map[int]int)
var candidates [][]int
for _, edge := range edges {
if p, exists := parent[edge[1]]; exists {
candidates = append(candidates, []int{p, edge[1]})
candidates = append(candidates, edge)
} else {
parent[edge[1]] = edge[0]
}
}
root := s.orbit(1, parent).node
if len(candidates) == 0 {
cycle := s.orbit(root, parent).seen
ans := []int{0, 0}
for _, edge := range edges {
if cycle[edge[0]] && cycle[edge[1]] {
ans = edge
}
}
return ans
}
children := make(map[int][]int)
for v, pv := range parent {
children[pv] = append(children[pv], v)
}
seen := make([]bool, N+1)
seen[0] = true
stack := []int{root}
for len(stack) > 0 {
node := stack[len(stack)-1]
stack = stack[:len(stack)-1]
if !seen[node] {
seen[node] = true
for _, c := range children[node] {
stack = append(stack, c)
}
}
}
for _, b := range seen {
if !b {
return candidates[0]
}
}
return candidates[1]
}
type OrbitResult struct {
node int
seen map[int]bool
}
func (s *Solution) orbit(node int, parent map[int]int) *OrbitResult {
seen := make(map[int]bool)
for {
if _, exists := parent[node]; !exists || seen[node] {
break
}
seen[node] = true
node = parent[node]
}
return &OrbitResult{node, seen}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 259. 3Sum Smaller
Сложность: medium
Дан массив из n целых чисел nums и целое число target. Найдите количество троек индексов i, j, k, удовлетворяющих условию 0 <= i < j < k < n и nums[i] + nums[j] + nums[k] < target.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте массив nums.
2⃣ Для каждого элемента nums[i] от 0 до n-3 найдите количество пар индексов j и k (где i < j < k), таких что nums[i] + nums[j] + nums[k] < target. Используйте функцию twoSumSmaller, которая ищет количество пар с суммой меньше заданного значения.
3⃣ В функции twoSumSmaller используйте бинарный поиск для поиска верхней границы индекса k и подсчета количества подходящих пар.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив из n целых чисел nums и целое число target. Найдите количество троек индексов i, j, k, удовлетворяющих условию 0 <= i < j < k < n и nums[i] + nums[j] + nums[k] < target.
Пример:
Input: nums = [-2,0,1,3], target = 2
Output: 2
Explanation: Because there are two triplets which sums are less than 2:
[-2,0,1]
[-2,0,3]
import "sort"
func threeSumSmaller(nums []int, target int) int {
sort.Ints(nums)
sum := 0
for i := 0; i < len(nums)-2; i++ {
sum += twoSumSmaller(nums, i+1, target-nums[i])
}
return sum
}
func twoSumSmaller(nums []int, startIndex int, target int) int {
sum := 0
for i := startIndex; i < len(nums)-1; i++ {
j := binarySearch(nums, i, target-nums[i])
sum += j - i
}
return sum
}
func binarySearch(nums []int, startIndex int, target int) int {
left, right := startIndex, len(nums)-1
for left < right {
mid := (left + right + 1) / 2
if nums[mid] < target {
left = mid
} else {
right = mid - 1
}
}
return left
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1305. All Elements in Two Binary Search Trees
Сложность: medium
Даны два бинарных дерева поиска root1 и root2. Вернуть список, содержащий все целые числа из обоих деревьев, отсортированные в порядке возрастания.
Пример:
👨💻 Алгоритм:
1⃣ Выполните итеративный обход в порядке возрастания обоих деревьев параллельно.
2⃣ На каждом шаге добавляйте наименьшее доступное значение в выходной список.
3⃣ Верните выходной список.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Даны два бинарных дерева поиска root1 и root2. Вернуть список, содержащий все целые числа из обоих деревьев, отсортированные в порядке возрастания.
Пример:
Input: root1 = [2,1,4], root2 = [1,0,3]
Output: [0,1,1,2,3,4]
package main
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func getAllElements(root1 *TreeNode, root2 *TreeNode) []int {
stack1, stack2 := []*TreeNode{}, []*TreeNode{}
output := []int{}
for root1 != nil || root2 != nil || len(stack1) > 0 || len(stack2) > 0 {
for root1 != nil {
stack1 = append(stack1, root1)
root1 = root1.Left
}
for root2 != nil {
stack2 = append(stack2, root2)
root2 = root2.Left
}
if len(stack2) == 0 || (len(stack1) > 0 && stack1[len(stack1)-1].Val <= stack2[len(stack2)-1].Val) {
root1 = stack1[len(stack1)-1]
stack1 = stack1[:len(stack1)-1]
output = append(output, root1.Val)
root1 = root1.Right
} else {
root2 = stack2[len(stack2)-1]
stack2 = stack2[:len(stack2)-1]
output = append(output, root2.Val)
root2 = root2.Right
}
}
return output
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 261. Graph Valid Tree
Сложность: medium
У вас есть граф из n узлов, помеченных от 0 до n - 1. Вам даны целое число n и список рёбер, где edges[i] = [ai, bi] указывает на то, что существует неориентированное ребро между узлами ai и bi в графе.
Верните true, если рёбра данного графа образуют допустимое дерево, и false в противном случае.
Пример:
👨💻 Алгоритм:
1⃣ Проверьте, что количество рёбер равно n - 1. Если нет, верните false.
2⃣ Используйте итеративный обход в глубину (DFS) для проверки связности графа и отсутствия циклов. Создайте стек для хранения узлов для посещения и множество для отслеживания посещённых узлов. Начните с узла 0.
3⃣ Если все узлы посещены и циклы не обнаружены, верните true. В противном случае, верните false.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
У вас есть граф из n узлов, помеченных от 0 до n - 1. Вам даны целое число n и список рёбер, где edges[i] = [ai, bi] указывает на то, что существует неориентированное ребро между узлами ai и bi в графе.
Верните true, если рёбра данного графа образуют допустимое дерево, и false в противном случае.
Пример:
Input: n = 5, edges = [[0,1],[0,2],[0,3],[1,4]]
Output: true
package main
func validTree(n int, edges [][]int) bool {
if len(edges) != n-1 {
return false
}
adjList := make([][]int, n)
for _, edge := range edges {
adjList[edge[0]] = append(adjList[edge[0]], edge[1])
adjList[edge[1]] = append(adjList[edge[1]], edge[0])
}
parent := make(map[int]int)
parent[0] = -1
queue := []int{0}
for len(queue) > 0 {
node := queue[0]
queue = queue[1:]
for _, neighbor := range adjList[node] {
if neighbor == parent[node] {
continue
}
if _, found := parent[neighbor]; found {
return false
}
parent[neighbor] = node
queue = append(queue, neighbor)
}
}
return len(parent) == n
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 736. Parse Lisp Expression
Сложность: hard
Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.
Пример:
👨💻 Алгоритм:
1⃣ Определите функцию для оценки выражений.
2⃣ Используйте рекурсивный подход для обработки различных типов выражений (let, add, mult, и переменных).
3⃣ Используйте словарь для отслеживания значений переменных с учетом области видимости.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.
Пример:
Input: expression = "(let x 2 (mult x (let x 3 y 4 (add x y))))"
Output: 14
package main
import (
"strconv"
"strings"
)
func evaluate(expression string) int {
return evaluateExpression(expression, map[string]int{})
}
func evaluateExpression(expression string, env map[string]int) int {
if expression[0] != '(' {
if val, err := strconv.Atoi(expression); err == nil {
return val
}
return env[expression]
}
tokens := tokenize(expression)
if tokens[0] == "let" {
for i := 1; i < len(tokens)-2; i += 2 {
env[tokens[i]] = evaluateExpression(tokens[i+1], env)
}
return evaluateExpression(tokens[len(tokens)-1], env)
} else if tokens[0] == "add" {
return evaluateExpression(tokens[1], env) + evaluateExpression(tokens[2], env)
} else if tokens[0] == "mult" {
return evaluateExpression(tokens[1], env) * evaluateExpression(tokens[2], env)
}
return 0
}
func tokenize(expression string) []string {
tokens := []string{}
token := ""
parens := 0
for _, char := range expression {
switch char {
case '(':
parens++
if parens == 1 {
continue
}
case ')':
parens--
if parens == 0 {
tokens = append(tokens, tokenize(token)...)
token = ""
continue
}
case ' ':
if parens == 1 {
if token != "" {
tokens = append(tokens, token)
token = ""
}
continue
}
}
token += string(char)
}
if token != "" {
tokens = append(tokens, token)
}
return tokens
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 94. Binary Tree Inorder Traversal
Сложность: easy
Дан корень бинарного дерева. Верните обход значений его узлов в симметричном порядке (inorder).
Пример:
👨💻 Алгоритм:
1⃣ Используем рекурсию:
- Обход в симметричном порядке: левый поддерево → текущий узел → правое поддерево.
2⃣ Вспомогательная функция:
- Рекурсивно вызывается для левого и правого поддеревьев.
- Добавляет значение текущего узла в результирующий массив.
3⃣ Результат:
- Итоговый срез
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан корень бинарного дерева. Верните обход значений его узлов в симметричном порядке (inorder).
Пример:
Input: root = [1,null,2,3]
Output: [1,3,2]
- Обход в симметричном порядке: левый поддерево → текущий узел → правое поддерево.
- Рекурсивно вызывается для левого и правого поддеревьев.
- Добавляет значение текущего узла в результирующий массив.
- Итоговый срез
res содержит последовательность узлов в симметричном обходе. type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func inorderTraversal(root *TreeNode) []int {
res := make([]int, 0)
helper(root, &res)
return res
}
func helper(root *TreeNode, res *[]int) {
if root != nil {
helper(root.Left, res)
*res = append(*res, root.Val)
helper(root.Right, res)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1481. Least Number of Unique Integers after K Removals
Сложность: medium
Дан массив целых чисел arr и целое число k. Найдите минимальное количество уникальных целых чисел после удаления ровно k элементов.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и построение частотного массива:
Создайте хеш-таблицу для отслеживания частот элементов массива arr.
Итеративно увеличивайте частоту элементов в хеш-таблице.
2⃣ Сортировка и удаление элементов:
Создайте массив частот и заполните его значениями из хеш-таблицы.
Отсортируйте массив частот.
Инициализируйте переменную для отслеживания числа удаленных элементов и итеративно добавляйте частоты, пока количество удаленных элементов не превысит k.
3⃣ Возвращение результата:
Если количество удаленных элементов превысило k, верните оставшееся количество уникальных элементов.
Если все элементы были удалены, верните 0.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел arr и целое число k. Найдите минимальное количество уникальных целых чисел после удаления ровно k элементов.
Пример:
Input: arr = [5,5,4], k = 1
Output: 1
Explanation: Remove the single 4, only 5 is left.
Создайте хеш-таблицу для отслеживания частот элементов массива arr.
Итеративно увеличивайте частоту элементов в хеш-таблице.
Создайте массив частот и заполните его значениями из хеш-таблицы.
Отсортируйте массив частот.
Инициализируйте переменную для отслеживания числа удаленных элементов и итеративно добавляйте частоты, пока количество удаленных элементов не превысит k.
Если количество удаленных элементов превысило k, верните оставшееся количество уникальных элементов.
Если все элементы были удалены, верните 0.
import "sort"
func findLeastNumOfUniqueInts(arr []int, k int) int {
freqMap := make(map[int]int)
for _, num := range arr {
freqMap[num]++
}
frequencies := make([]int, 0, len(freqMap))
for _, freq := range freqMap {
frequencies = append(frequencies, freq)
}
sort.Ints(frequencies)
elementsRemoved := 0
for i, freq := range frequencies {
elementsRemoved += freq
if elementsRemoved > k {
return len(frequencies) - i
}
}
return 0
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
🎉 easyoffer 2.0 — релиз уже в этом месяце!
Вас ждут новые фичи, о которых мы ранее даже не упоминали. Они сделают путь к офферам ещё быстрее и эффективнее. Расскажу о них чуть позже 👀
В честь запуска мы готовим ограниченную акцию:
Первые 500 покупателей получат:
🚀 PRO тариф на 1 год с 50% скидкой
Что нужно сделать:
🔔 Подпишитесь на этот Telegram-канал, чтобы первыми узнать о старте релиза. Сообщение появится в нем раньше, чем где-либо еще — вы успеете попасть в число первых 500 и получить максимальную выгоду. 🎁 А еще только для подписчиков канала ценный бонус в подарок к PRO тарифу.
📅 Официальный запуск — уже совсем скоро.
Следите за новостями и не пропустите старт!
Вас ждут новые фичи, о которых мы ранее даже не упоминали. Они сделают путь к офферам ещё быстрее и эффективнее. Расскажу о них чуть позже 👀
В честь запуска мы готовим ограниченную акцию:
Первые 500 покупателей получат:
🚀 PRO тариф на 1 год с 50% скидкой
Что нужно сделать:
🔔 Подпишитесь на этот Telegram-канал, чтобы первыми узнать о старте релиза. Сообщение появится в нем раньше, чем где-либо еще — вы успеете попасть в число первых 500 и получить максимальную выгоду. 🎁 А еще только для подписчиков канала ценный бонус в подарок к PRO тарифу.
📅 Официальный запуск — уже совсем скоро.
Следите за новостями и не пропустите старт!
Задача: 333. Largest BST Subtree
Сложность: medium
Дан корень бинарного дерева, найдите самое большое поддерево, которое также является деревом бинарного поиска (BST), где "самое большое" означает поддерево с наибольшим количеством узлов.
Дерево бинарного поиска (BST) — это дерево, в котором все узлы соблюдают следующие свойства:
Значения в левом поддереве меньше значения их родительского (корневого) узла.
Значения в правом поддереве больше значения их родительского (корневого) узла.
Примечание: Поддерево должно включать всех своих потомков.
Пример:
👨💻 Алгоритм:
1⃣ Пост-упорядоченный обход дерева:
Обходите каждую ноду дерева в пост-упорядоченном порядке (left-right-root). Это позволит гарантировать, что обе поддеревья ноды уже проверены на соответствие критериям BST перед проверкой самой ноды.
2⃣ Проверка условий BST для каждой ноды:
Для каждой ноды определите минимальное и максимальное значения в её левом и правом поддеревьях. Проверьте, удовлетворяет ли текущее поддерево условиям BST:
- значение текущей ноды должно быть больше максимального значения в левом поддереве.
- значение текущей ноды должно быть меньше минимального значения в правом поддереве.
Если условия выполняются, вычислите размер текущего поддерева как сумму размеров левого и правого поддеревьев плюс 1 (для текущей ноды).
3⃣ Возврат максимального размера BST:
Если текущее поддерево не является BST, верните максимальный размер BST из его левого или правого поддерева.
В конце рекурсивного обхода верните максимальный размер BST в дереве.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень бинарного дерева, найдите самое большое поддерево, которое также является деревом бинарного поиска (BST), где "самое большое" означает поддерево с наибольшим количеством узлов.
Дерево бинарного поиска (BST) — это дерево, в котором все узлы соблюдают следующие свойства:
Значения в левом поддереве меньше значения их родительского (корневого) узла.
Значения в правом поддереве больше значения их родительского (корневого) узла.
Примечание: Поддерево должно включать всех своих потомков.
Пример:
Input: root = [10,5,15,1,8,null,7]
Output: 3
Explanation: The Largest BST Subtree in this case is the highlighted one. The return value is the subtree's size, which is 3.
Обходите каждую ноду дерева в пост-упорядоченном порядке (left-right-root). Это позволит гарантировать, что обе поддеревья ноды уже проверены на соответствие критериям BST перед проверкой самой ноды.
Для каждой ноды определите минимальное и максимальное значения в её левом и правом поддеревьях. Проверьте, удовлетворяет ли текущее поддерево условиям BST:
- значение текущей ноды должно быть больше максимального значения в левом поддереве.
- значение текущей ноды должно быть меньше минимального значения в правом поддереве.
Если условия выполняются, вычислите размер текущего поддерева как сумму размеров левого и правого поддеревьев плюс 1 (для текущей ноды).
Если текущее поддерево не является BST, верните максимальный размер BST из его левого или правого поддерева.
В конце рекурсивного обхода верните максимальный размер BST в дереве.
import "math"
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
type NodeValue struct {
minNode, maxNode, maxSize int
}
func largestBSTSubtreeHelper(root *TreeNode) NodeValue {
if root == nil {
return NodeValue{math.MaxInt64, math.MinInt64, 0}
}
left := largestBSTSubtreeHelper(root.Left)
right := largestBSTSubtreeHelper(root.Right)
if left.maxNode < root.Val && root.Val < right.minNode {
return NodeValue{min(root.Val, left.minNode), max(root.Val, right.maxNode),
left.maxSize + right.maxSize + 1}
}
return NodeValue{math.MinInt64, math.MaxInt64, max(left.maxSize, right.maxSize)}
}
func largestBSTSubtree(root *TreeNode) int {
return largestBSTSubtreeHelper(root).maxSize
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1243. Array Transformation
Сложность: easy
Если задан исходный массив arr, то каждый день вы создаете новый массив, используя массив предыдущего дня. В i-й день вы выполняете следующие операции над массивом дня i-1, чтобы получить массив дня i: если элемент меньше своего левого и правого соседа, то этот элемент увеличивается. Если элемент больше своего левого и правого соседа, то этот элемент уменьшается. Первый и последний элементы никогда не меняются. Через несколько дней массив не меняется. Верните этот окончательный массив.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация нового массива с такими же значениями, как у исходного массива.
Циклически изменяем массив в соответствии с правилами, пока он не перестанет меняться.
2⃣ Для каждого элемента массива проверяем, изменяется ли он в зависимости от его левого и правого соседей.
Если элемент меньше своего левого и правого соседей, увеличиваем его.
Если элемент больше своего левого и правого соседей, уменьшаем его.
3⃣ Первый и последний элементы массива остаются неизменными.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Если задан исходный массив arr, то каждый день вы создаете новый массив, используя массив предыдущего дня. В i-й день вы выполняете следующие операции над массивом дня i-1, чтобы получить массив дня i: если элемент меньше своего левого и правого соседа, то этот элемент увеличивается. Если элемент больше своего левого и правого соседа, то этот элемент уменьшается. Первый и последний элементы никогда не меняются. Через несколько дней массив не меняется. Верните этот окончательный массив.
Пример:
Input: arr = [6,2,3,4]
Output: [6,3,3,4]Циклически изменяем массив в соответствии с правилами, пока он не перестанет меняться.
Если элемент меньше своего левого и правого соседей, увеличиваем его.
Если элемент больше своего левого и правого соседей, уменьшаем его.
func transformArray(arr []int) []int {
changed := true
for changed {
changed = false
newArr := make([]int, len(arr))
copy(newArr, arr)
for i := 1; i < len(arr)-1; i++ {
if arr[i] < arr[i-1] && arr[i] < arr[i+1] {
newArr[i]++
changed = true
} else if arr[i] > arr[i-1] && arr[i] > arr[i+1] {
newArr[i]--
changed = true
}
}
arr = newArr
}
return arr
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 731. My Calendar II
Сложность: medium
Вы создаете программу для использования в качестве календаря. Мы можем добавить новое событие, если его добавление не приведет к тройному бронированию. Тройное бронирование происходит, когда три события имеют некоторое непустое пересечение (т.е, Событие можно представить в виде пары целых чисел start и end, которая представляет собой бронирование на полуоткрытом интервале [start, end), диапазоне вещественных чисел x таких, что start <= x < end. Реализация класса MyCalendarTwo: MyCalendarTwo() Инициализирует объект календаря. boolean book(int start, int end) Возвращает true, если событие может быть успешно добавлено в календарь, не вызывая тройного бронирования. В противном случае возвращается false и событие не добавляется в календарь.
Пример:
👨💻 Алгоритм:
1⃣ Создайте два списка: один для отслеживания всех событий, второй для отслеживания пересечений. подпоследовательностей.
2⃣ При добавлении нового события сначала проверьте, не пересекается ли оно с любыми существующими пересечениями.
3⃣ Если пересечение не обнаружено, добавьте новое событие и обновите список пересечений при необходимости.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вы создаете программу для использования в качестве календаря. Мы можем добавить новое событие, если его добавление не приведет к тройному бронированию. Тройное бронирование происходит, когда три события имеют некоторое непустое пересечение (т.е, Событие можно представить в виде пары целых чисел start и end, которая представляет собой бронирование на полуоткрытом интервале [start, end), диапазоне вещественных чисел x таких, что start <= x < end. Реализация класса MyCalendarTwo: MyCalendarTwo() Инициализирует объект календаря. boolean book(int start, int end) Возвращает true, если событие может быть успешно добавлено в календарь, не вызывая тройного бронирования. В противном случае возвращается false и событие не добавляется в календарь.
Пример:
Input
["MyCalendarTwo", "book", "book", "book", "book", "book", "book"]
[[], [10, 20], [50, 60], [10, 40], [5, 15], [5, 10], [25, 55]]
Output
[null, true, true, true, false, true, true]
package main
type MyCalendarTwo struct {
events [][2]int
overlaps [][2]int
}
func Constructor() MyCalendarTwo {
return MyCalendarTwo{}
}
func (this *MyCalendarTwo) Book(start int, end int) bool {
for _, overlap := range this.overlaps {
if start < overlap[1] && end > overlap[0] {
return false
}
}
for _, event := range this.events {
if start < event[1] && end > event[0] {
this.overlaps = append(this.overlaps, [2]int{max(start, event[0]), min(end, event[1])})
}
}
this.events = append(this.events, [2]int{start, end})
return true
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 410. Split Array Largest Sum
Сложность: easy
Учитывая целочисленный массив nums и целое число k, разбейте nums на k непустых подмассивов так, чтобы наибольшая сумма любого подмассива была минимальна. Верните минимизированную наибольшую сумму разбиения. Подмассив - это смежная часть массива.
Пример:
👨💻 Алгоритм:
1⃣ Определите границы для бинарного поиска: минимальная сумма равна максимальному элементу массива, максимальная сумма равна сумме всех элементов массива.
2⃣ Выполните бинарный поиск по этим границам. Для каждой средней суммы проверьте, можно ли разбить массив на k подмассивов, чтобы максимальная сумма подмассива не превышала эту среднюю сумму.
3⃣ Если возможно разбить массив для данной средней суммы, уменьшите верхнюю границу. Если нет, увеличьте нижнюю границу. Повторяйте до тех пор, пока границы не сойдутся.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Учитывая целочисленный массив nums и целое число k, разбейте nums на k непустых подмассивов так, чтобы наибольшая сумма любого подмассива была минимальна. Верните минимизированную наибольшую сумму разбиения. Подмассив - это смежная часть массива.
Пример:
Input: nums = [7,2,5,10,8], k = 2
Output: 18
package main
func splitArray(nums []int, k int) int {
left, right := max(nums), sum(nums)
for left < right {
mid := (left + right) / 2
if canSplit(nums, k, mid) {
right = mid
} else {
left = mid + 1
}
}
return left
}
func canSplit(nums []int, k int, maxSum int) bool {
currentSum, subarrays := 0, 1
for _, num := range nums {
if currentSum + num > maxSum {
currentSum = num
subarrays++
if subarrays > k {
return false
}
} else {
currentSum += num
}
}
return true
}
func max(nums []int) int {
maxNum := nums[0]
for _, num := range nums {
if num > maxNum {
maxNum = num
}
}
return maxNum
}
func sum(nums []int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 979. Distribute Coins in Binary Tree
Сложность: medium
Вам дан корень бинарного дерева с n узлами, где каждый узел в дереве содержит node.val монет. Всего по всему дереву распределено n монет.
За один ход мы можем выбрать два смежных узла и переместить одну монету из одного узла в другой. Ход может быть как от родителя к ребенку, так и от ребенка к родителю.
Верните минимальное количество ходов, необходимых для того, чтобы каждый узел имел ровно одну монету.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и определение рекурсивной функции. Инициализируйте переменную moves = 0. Определите рекурсивную функцию dfs, которая считает количество перемещений монет. Базовый случай: если текущий узел равен null, верните 0.
2⃣ Рекурсивный обход дерева. Внутри dfs вызовите dfs для левого и правого поддеревьев, чтобы получить количество монет, которые нужно переместить в каждом поддереве. Вычислите количество перемещений для текущего узла: добавьте абсолютные значения перемещаемых монет в moves.
3⃣ Возвращение результата. Верните количество монет, которые текущий узел может передать своему родителю: значение узла плюс количество монет в левом и правом поддеревьях минус 1. Вызовите dfs от корня дерева и верните moves.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан корень бинарного дерева с n узлами, где каждый узел в дереве содержит node.val монет. Всего по всему дереву распределено n монет.
За один ход мы можем выбрать два смежных узла и переместить одну монету из одного узла в другой. Ход может быть как от родителя к ребенку, так и от ребенка к родителю.
Верните минимальное количество ходов, необходимых для того, чтобы каждый узел имел ровно одну монету.
Пример:
Input: root = [3,0,0]
Output: 2
Explanation: From the root of the tree, we move one coin to its left child, and one coin to its right child.
func distributeCoins(root *TreeNode) int {
moves := 0
var dfs func(*TreeNode) int
dfs = func(current *TreeNode) int {
if current == nil {
return 0
}
leftCoins := dfs(current.Left)
rightCoins := dfs(current.Right)
moves += abs(leftCoins) + abs(rightCoins)
return current.Val - 1 + leftCoins + rightCoins
}
dfs(root)
return moves
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 131. Palindrome Partitioning
Сложность: medium
Дана строка s. Разделите строку таким образом, чтобы каждая подстрока разделения была палиндромом. Верните все возможные варианты разделения строки s на палиндромы.
Пример:
👨💻 Алгоритм:
1⃣ Инициация рекурсивного обхода:
В алгоритме обратного отслеживания (backtracking) мы рекурсивно пробегаем по строке, используя метод поиска в глубину (depth-first search). Для каждого рекурсивного вызова задаётся начальный индекс строки start.
Итеративно генерируем все возможные подстроки, начиная с индекса start. Индекс end увеличивается от start до конца строки.
2⃣ Проверка на палиндром и продолжение поиска:
Для каждой сгенерированной подстроки проверяем, является ли она палиндромом.
Если подстрока оказывается палиндромом, она становится потенциальным кандидатом. Добавляем подстроку в currentList и выполняем поиск в глубину для оставшейся части строки. Если текущая подстрока заканчивается на индексе end, то end+1 становится начальным индексом для следующего рекурсивного вызова.
3⃣ Возврат (Backtracking) и сохранение результатов:
Возвращаемся, если начальный индекс start больше или равен длине строки, и добавляем currentList в результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дана строка s. Разделите строку таким образом, чтобы каждая подстрока разделения была палиндромом. Верните все возможные варианты разделения строки s на палиндромы.
Пример:
Input: s = "aab"
Output: [["a","a","b"],["aa","b"]]
В алгоритме обратного отслеживания (backtracking) мы рекурсивно пробегаем по строке, используя метод поиска в глубину (depth-first search). Для каждого рекурсивного вызова задаётся начальный индекс строки start.
Итеративно генерируем все возможные подстроки, начиная с индекса start. Индекс end увеличивается от start до конца строки.
Для каждой сгенерированной подстроки проверяем, является ли она палиндромом.
Если подстрока оказывается палиндромом, она становится потенциальным кандидатом. Добавляем подстроку в currentList и выполняем поиск в глубину для оставшейся части строки. Если текущая подстрока заканчивается на индексе end, то end+1 становится начальным индексом для следующего рекурсивного вызова.
Возвращаемся, если начальный индекс start больше или равен длине строки, и добавляем currentList в результат.
func partition(s string) [][]string {
res := [][]string{}
dfs(s, []string{}, &res)
return res
}
func dfs(s string, path []string, res *[][]string) {
if len(s) == 0 {
*res = append(*res, append([]string(nil), path...))
return
}
for i := 1; i <= len(s); i++ {
if isPalindrome(s[:i]) {
dfs(s[i:], append(path, s[:i]), res)
}
}
}
func isPalindrome(s string) bool {
lo, hi := 0, len(s)-1
for lo < hi {
if s[lo] != s[hi] {
return false
}
lo++
hi--
}
return true
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1035. Uncrossed Lines
Сложность: medium
Вам даны два целочисленных массива nums1 и nums2. Запишем целые числа nums1 и nums2 (в том порядке, в котором они даны) на двух отдельных горизонтальных линиях. Мы можем провести соединительные линии: прямую линию, соединяющую два числа nums1[i] и nums2[j] так, что: nums1[i] == nums2[j], и проведенная линия не пересекает никакую другую соединительную (негоризонтальную) линию. Обратите внимание, что соединительная линия не может пересекаться даже в конечных точках (т.е, каждое число может принадлежать только одной соединительной линии). Верните максимальное количество соединительных линий, которые мы можем нарисовать таким образом.
Пример:
👨💻 Алгоритм:
1⃣ Определение задачи как задачи о нахождении наибольшей общей подпоследовательности (LCS):
Эта задача является классической задачей динамического программирования, где нам нужно найти максимальную длину наибольшей общей подпоследовательности (LCS) между nums1 и nums2.
2⃣ Построение таблицы динамического программирования:
Создайте двумерный массив dp, где dp[i][j] будет представлять длину наибольшей общей подпоследовательности для подмассивов nums1[0..i-1] и nums2[0..j-1].
Инициализируйте первый ряд и первый столбец нулями, так как если один из массивов пуст, LCS также будет пустым.
3⃣ Заполнение таблицы динамического программирования:
Пройдите по элементам массивов nums1 и nums2. Если текущие элементы совпадают, увеличьте значение ячейки dp[i][j] на 1 от диагонального значения dp[i-1][j-1]. Если не совпадают, установите значение ячейки dp[i][j] как максимальное из значений dp[i-1][j] и dp[i][j-1].
Результат будет находиться в ячейке dp[nums1.length][nums2.length].
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам даны два целочисленных массива nums1 и nums2. Запишем целые числа nums1 и nums2 (в том порядке, в котором они даны) на двух отдельных горизонтальных линиях. Мы можем провести соединительные линии: прямую линию, соединяющую два числа nums1[i] и nums2[j] так, что: nums1[i] == nums2[j], и проведенная линия не пересекает никакую другую соединительную (негоризонтальную) линию. Обратите внимание, что соединительная линия не может пересекаться даже в конечных точках (т.е, каждое число может принадлежать только одной соединительной линии). Верните максимальное количество соединительных линий, которые мы можем нарисовать таким образом.
Пример:
Input: nums1 = [1,4,2], nums2 = [1,2,4]
Output: 2
Эта задача является классической задачей динамического программирования, где нам нужно найти максимальную длину наибольшей общей подпоследовательности (LCS) между nums1 и nums2.
Создайте двумерный массив dp, где dp[i][j] будет представлять длину наибольшей общей подпоследовательности для подмассивов nums1[0..i-1] и nums2[0..j-1].
Инициализируйте первый ряд и первый столбец нулями, так как если один из массивов пуст, LCS также будет пустым.
Пройдите по элементам массивов nums1 и nums2. Если текущие элементы совпадают, увеличьте значение ячейки dp[i][j] на 1 от диагонального значения dp[i-1][j-1]. Если не совпадают, установите значение ячейки dp[i][j] как максимальное из значений dp[i-1][j] и dp[i][j-1].
Результат будет находиться в ячейке dp[nums1.length][nums2.length].
import (
"sort"
"math"
)
func allCellsDistOrder(rows int, cols int, rCenter int, cCenter int) [][]int {
cells := make([][3]int, 0, rows*cols)
for r := 0; r < rows; r++ {
for c := 0; c < cols; c++ {
distance := int(math.Abs(float64(r - rCenter)) + math.Abs(float64(c - cCenter)))
cells = append(cells, [3]int{distance, r, c})
}
}
sort.Slice(cells, func(i, j int) bool {
return cells[i][0] < cells[j][0]
})
result := make([][]int, len(cells))
for i, cell := range cells {
result[i] = []int{cell[1], cell[2]}
}
return result
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM