Golang | LeetCode
3.91K subscribers
173 photos
1.05K links
Cайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp

Тесты t.iss.one/+MVqzqT6ZzFFhYjhi
Вопросы собесов t.iss.one/+ajHN0OKU1okyZDky
Вакансии t.iss.one/+mX_RBWjiMTExODUy
Download Telegram
#hard
Задача: 212. Word Search II

Дана m на n доска символов и список строк words, верните все слова, находящиеся на доске.

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

Пример:
Input: board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
Output: ["eat","oath"]


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

1️⃣ Построение Trie:
Постройте структуру Trie из слов в словаре. Trie будет использоваться для процесса сопоставления позже.

2️⃣ Запуск обхода в глубину (Backtracking) с каждой ячейки:
Начните обход доски с каждой ячейки. Если существует слово в словаре, которое начинается с буквы в данной ячейке, начните рекурсивный вызов функции backtracking(cell).

3️⃣ Обход соседних ячеек:
В функции backtracking(cell) исследуйте соседние ячейки (i.e. neighborCell) вокруг текущей ячейки для следующего рекурсивного вызова backtracking(neighborCell).
На каждом вызове проверяйте, соответствует ли последовательность букв, которую мы прошли до сих пор, какому-либо слову в словаре, используя структуру Trie, построенную в начале.

😎
package main

type TrieNode struct {
children map[rune]*TrieNode
word string
}

type Solution struct {
board [][]byte
result []string
}

func findWords(board [][]byte, words []string) []string {
root := buildTrie(words)
sol := Solution{board: board}

for row := range board {
for col := range board[0] {
if _, ok := root.children[rune(board[row][col])]; ok {
sol.backtrack(row, col, root)
}
}
}

return sol.result
}

func buildTrie(words []string) *TrieNode {
root := &TrieNode{children: make(map[rune]*TrieNode)}
for _, word := range words {
node := root
for _, letter := range word {
if node.children[letter] == nil {
node.children[letter] = &TrieNode{children: make(map[rune]*TrieNode)}
}
node = node.children[letter]
}
node.word = word
}
return root
}

func (sol *Solution) backtrack(row, col int, parent *TrieNode) {
letter := rune(sol.board[row][col])
currNode := parent.children[letter]

if currNode.word != "" {
sol.result = append(sol.result, currNode.word)
currNode.word = ""
}

sol.board[row][col] = '#'
rowOffset := []int{-1, 0, 1, 0}
colOffset := []int{0, 1, 0, -1}

for i := 0; i < 4; i++ {
newRow := row + rowOffset[i]
newCol := col + colOffset[i]
if newRow >= 0 && newRow < len(sol.board) && newCol >= 0 && newCol < len(sol.board[0]) {
if _, ok := currNode.children[rune(sol.board[newRow][newCol])]; ok {
sol.backtrack(newRow, newCol, currNode)
}
}
}

sol.board[row][col] = byte(letter)
if len(currNode.children) == 0 {
delete(parent.children, letter)
}
}

func main() {
board := [][]byte{
{'o', 'a', 'a', 'n'},
{'e', 't', 'a', 'e'},
{'i', 'h', 'k', 'r'},
{'i', 'f', 'l', 'v'},
}
words := []string{"oath", "pea", "eat", "rain"}
result := findWords(board, words)
for _, word := range result {
println(word)
}
}


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

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

Есть ряд из n домов, где каждый дом можно покрасить в один из трёх цветов: красный, синий или зелёный. Стоимость покраски каждого дома в определённый цвет разная. Необходимо покрасить все дома так, чтобы никакие два соседних дома не были окрашены в один и тот же цвет.

Стоимость покраски каждого дома в определённый цвет представлена в виде матрицы стоимости n x 3.

Например, costs[0][0] — это стоимость покраски дома 0 в красный цвет; costs[1][2] — это стоимость покраски дома 1 в зелёный цвет и так далее...
Верните минимальную стоимость покраски всех домов.

Пример:
Input: costs = [[17,2,17],[16,16,5],[14,3,19]]
Output: 10
Explanation: Paint house 0 into blue, paint house 1 into green, paint house 2 into blue.
Minimum cost: 2 + 5 + 3 = 10.


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

1️⃣Инициализируйте массив dp размера n x 3 для хранения минимальных затрат на покраску домов. Установите начальные значения для первого дома: dp[0][0] = costs[0][0], dp[0][1] = costs[0][1], dp[0][2] = costs[0][2].

2️⃣Для каждого дома i от 1 до n-1 обновите значения массива dp:
dp[i][0] = costs[i][0] + min(dp[i-1][1], dp[i-1][2])
dp[i][1] = costs[i][1] + min(dp[i-1][0], dp[i-1][2])
dp[i][2] = costs[i][2] + min(dp[i-1][0], dp[i-1][1])

3️⃣Верните минимальное значение из последней строки массива dp: min(dp[n-1][0], dp[n-1][1], dp[n-1][2]).

😎 Решение:
func minCost(costs [][]int) int {
n := len(costs)
dp := make([][3]int, n)
dp[0] = [3]int{costs[0][0], costs[0][1], costs[0][2]}

for i := 1; i < n; i++ {
dp[i][0] = costs[i][0] + min(dp[i-1][1], dp[i-1][2])
dp[i][1] = costs[i][1] + min(dp[i-1][0], dp[i-1][2])
dp[i][2] = costs[i][2] + min(dp[i-1][0], dp[i-1][1])
}

return min(dp[n-1][0], dp[n-1][1], dp[n-1][2])
}

func min(a, b int) int {
if a < b {
return a
}
return b
}


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

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

Дано корневое дерево, верните все пути от корня до листа в любом порядке.

Лист — это узел без детей.

Пример:
Input: root = [1,2,3,null,5]
Output: ["1->2->5","1->3"]


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

1️⃣Если текущий узел не является null, добавьте его значение к текущему пути.
Если текущий узел является листом (не имеет дочерних узлов), добавьте текущий путь в список путей.
Если текущий узел не является листом, добавьте "->" к текущему пути и рекурсивно вызовите функцию для левого и правого дочерних узлов.

2️⃣Начните с корневого узла, пустого пути и пустого списка путей.

3️⃣Верните список всех путей от корня до листа.

😎 Решение:
func constructPaths(root *TreeNode, path string, paths *[]string) {
if root != nil {
path += fmt.Sprintf("%d", root.Val)
if root.Left == nil && root.Right == nil {
*paths = append(*paths, path)
} else {
path += "->"
constructPaths(root.Left, path, paths)
constructPaths(root.Right, path, paths)
}
}
}

func binaryTreePaths(root *TreeNode) []string {
var paths []string
constructPaths(root, "", &paths)
return paths
}


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
#easy
Задача: 258. Add Digits

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

Пример:
Input: num = 38
Output: 2
Explanation: The process is
38 --> 3 + 8 --> 11
11 --> 1 + 1 --> 2
Since 2 has only one digit, return it.


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

1️⃣Инициализируйте переменную digital_root значением 0.

2️⃣В цикле, пока num больше 0:
Добавьте к digital_root последнюю цифру num.
Уменьшите num, удалив последнюю цифру.
Если num равно 0 и digital_root больше 9, присвойте num значение digital_root и сбросьте digital_root в 0.

3️⃣Верните значение digital_root.

😎 Решение:
func addDigits(num int) int {
digital_root := 0
for num > 0 {
digital_root += num % 10
num /= 10
if num == 0 && digital_root > 9 {
num = digital_root
digital_root = 0
}
}
return digital_root
}


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

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

Дан массив из 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]


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

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

2️⃣Для каждого элемента nums[i] от 0 до n-3 найдите количество пар индексов j и k (где i < j < k), таких что nums[i] + nums[j] + nums[k] < target. Используйте функцию twoSumSmaller, которая ищет количество пар с суммой меньше заданного значения.

3️⃣В функции twoSumSmaller используйте бинарный поиск для поиска верхней границы индекса k и подсчета количества подходящих пар.

😎 Решение:
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
🤔1
#medium
Задача: 260. Single Number III

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

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

Пример:
Input: nums = [1,2,1,3,2,5]
Output: [3,5]
Explanation: [5, 3] is also a valid answer.


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

1️⃣Выполните XOR для всех элементов массива nums. Это даст результат, который является XOR двух уникальных чисел.

2️⃣Найдите бит, который отличается в этих двух числах, чтобы разделить все числа в массиве на две группы.

3️⃣Выполните XOR для каждой группы, чтобы найти два уникальных числа.

😎 Решение:
func singleNumber(nums []int) []int {
xor := 0
for _, num := range nums {
xor ^= num
}
diff := xor & -xor
res := []int{0, 0}
for _, num := range nums {
if num&diff == 0 {
res[0] ^= num
} else {
res[1] ^= num
}
}
return res
}


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
#medium
Задача: 261. Graph Valid Tree

У вас есть граф из 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


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

1️⃣Проверьте, что количество рёбер равно n - 1. Если нет, верните false.

2️⃣Используйте итеративный обход в глубину (DFS) для проверки связности графа и отсутствия циклов. Создайте стек для хранения узлов для посещения и множество для отслеживания посещённых узлов. Начните с узла 0.

3️⃣Если все узлы посещены и циклы не обнаружены, верните true. В противном случае, верните false.

😎 Решение:
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
🤔1
#easy
Задача: 263. Ugly Number

Уродливое число — это положительное целое число, простые множители которого ограничены числами 2, 3 и 5.

Дано целое число n, верните true, если n является уродливым числом.

Пример:
Input: n = 6
Output: true
Explanation: 6 = 2 × 3


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

1️⃣Если данное целое число n неположительное, верните false, так как неположительное число не может быть уродливым.

2️⃣Определите функцию keepDividingWhenDivisible, которая принимает два аргумента: делимое и делитель. Эта функция будет делить делимое на делитель до тех пор, пока оно делится без остатка. Функция возвращает измененное делимое. Последовательно примените эту функцию к n с делителями 2, 3 и 5.

3️⃣Если после всех делений n равно 1, верните true, иначе верните false.

😎 Решение:
package main

func isUgly(n int) bool {
if n <= 0 {
return false
}
for _, factor := range []int{2, 3, 5} {
n = keepDividingWhenDivisible(n, factor)
}
return n == 1
}

func keepDividingWhenDivisible(dividend, divisor int) int {
for dividend%divisor == 0 {
dividend /= divisor
}
return dividend
}


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🤔1
#medium
Задача: 240. Search a 2D Matrix II

Напишите эффективный алгоритм, который ищет значение target в матрице целых чисел размером m на n. У этой матрицы есть следующие свойства:

Целые числа в каждой строке отсортированы по возрастанию слева направо.
Целые числа в каждом столбце отсортированы по возрастанию сверху вниз.

Пример:
Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
Output: true


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

1️⃣Проверка матрицы: Перед началом поиска убедитесь, что матрица не пуста и не содержит null.

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

3️⃣Бинарный поиск и завершение: Продолжайте бинарный поиск до тех пор, пока не исчерпаете все диагонали (в этом случае возвращается False) или пока не найдете целевое значение (в этом случае возвращается True). Функция бинарного поиска должна уметь работать как с рядами, так и с колонками матрицы.

😎 Решение:
type Solution struct{}

func (s *Solution) binarySearch(matrix [][]int, target, start int, vertical bool) bool {
lo := start
hi := len(matrix[0]) - 1
if !vertical {
hi = len(matrix) - 1
}

for hi >= lo {
mid := (lo + hi) / 2
var value int
if vertical {
value = matrix[start][mid]
} else {
value = matrix[mid][start]
}

if value < target {
lo = mid + 1
} else if value > target {
hi = mid - 1
} else {
return true
}
}
return false
}

func (s *Solution) searchMatrix(matrix [][]int, target int) bool {
if len(matrix) == 0 || len(matrix[0]) == 0 {
return false
}

shorterDim := len(matrix)
if len(matrix[0]) < shorterDim {
shorterDim = len(matrix[0])
}

for i := 0; i < shorter


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
#easy
Задача: 242. Valid Anagram

Даны две строки s и t, верните true, если t является анаграммой s, и false в противном случае.

Анаграмма — это слово или фраза, сформированная путём перестановки букв другого слова или фразы, обычно используя все исходные буквы ровно один раз.

Пример:
Input: s = "anagram", t = "nagaram"
Output: true


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

1️⃣Создайте массив размером 26 для подсчета частот каждой буквы (поскольку s и t содержат только буквы от 'a' до 'z').

2️⃣Пройдитесь по строке s, увеличивая счетчик соответствующей буквы. Затем пройдитесь по строке t, уменьшая счетчик для каждой буквы.

3️⃣Проверьте, не опустился ли счетчик ниже нуля во время обхода строки t. Если это произошло, значит в t есть лишняя буква, которой нет в s, и следует вернуть false. Если после проверки всех букв все счетчики равны нулю, возвращайте true, указывая на то, что t является анаграммой s.

😎 Решение:
func isAnagram(s string, t string) bool {
if len(s) != len(t) {
return false
}
count := [26]int{}
for i := range s {
count[s[i]-'a']++
count[t[i]-'a']--
}
for _, c := range count {
if c != 0 {
return false
}
}
return true
}


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
#easy
Задача: 243. Shortest Word Distance

Дан массив строк wordsDict и две разные строки, которые уже существуют в массиве: word1 и word2. Верните кратчайшее расстояние между этими двумя словами в списке.

Пример:
Input: wordsDict = ["practice", "makes", "perfect", "coding", "makes"], word1 = "coding", word2 = "practice"
Output: 3


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

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

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

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
🤔1
#medium
Задача: 244. Shortest Word Distance II

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

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

WordDistance(String[] wordsDict) инициализирует объект с массивом строк wordsDict.
int shortest(String word1, String word2) возвращает наименьшее расстояние между word1 и word2 в массиве wordsDict.

Пример:
Input
["WordDistance", "shortest", "shortest"]
[[["practice", "makes", "perfect", "coding", "makes"]], ["coding", "practice"], ["makes", "coding"]]
Output
[null, 3, 1]
Explanation
WordDistance wordDistance = new WordDistance(["practice", "makes", "perfect", "coding", "makes"]);
wordDistance.shortest("coding", "practice"); // return 3
wordDistance.shortest("makes", "coding"); // return 1


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

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

2️⃣Для данной пары слов получите список индексов (вхождений в исходный массив слов). Назовём эти два массива loc1 и loc2. Инициализируйте две переменные-указателя l1 = 0 и l2 = 0.

3️⃣Для данных l1 и l2 обновите (если возможно) минимальную разницу (расстояние) до текущего момента, т.е. dist = min(dist, abs(loc1[l1] - loc2[l2])). Затем проверьте, если loc1[l1] < loc2[l2], и если это так, переместите l1 на один шаг вперёд, т.е. l1 = l1 + 1. В противном случае, переместите l2 на один шаг вперёд, т.е. l2 = l2 + 1. Продолжайте это делать, пока все элементы в меньшем из двух массивов позиций не будут обработаны. Верните глобальное минимальное расстояние между словами.

😎 Решение:
package main

import (
"math"
)

type WordDistance struct {
locations map[string][]int
}

func Constructor(words []string) WordDistance {
locations := make(map[string][]int)
for i, word := range words {
locations[word] = append(locations[word], i)
}
return WordDistance{locations: locations}
}

func (this *WordDistance) Shortest(word1 string, word2 string) int {
loc1 := this.locations[word1]
loc2 := this.locations[word2]
l1, l2 := 0, 0
minDiff := math.MaxInt32

for l1 < len(loc1) && l2 < len(loc2) {
minDiff = min(minDiff, abs(loc1[l1]-loc2[l2]))
if loc1[l1] < loc2[l2] {
l1++
} else {
l2++
}
}
return minDiff
}

func min(a, b int) int {
if a < b {
return a
}
return b
}

func abs(a int) int {
if a < 0 {
return -a
}
return a
}


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
#medium
Задача: 245. Shortest Word Distance II

Дан массив строк wordsDict и две строки word1 и word2, которые уже существуют в массиве. Верните наименьшее расстояние между вхождениями этих двух слов в списке.

Обратите внимание, что word1 и word2 могут быть одинаковыми. Гарантируется, что они представляют собой два отдельных слова в списке.

Пример:
Input: wordsDict = ["practice", "makes", "perfect", "coding", "makes"], word1 = "makes", word2 = "coding"
Output: 1


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

1️⃣Переберите список wordsDict и сохраните индексы слова word1 в список indices1 и индексы слова word2 в список indices2. Инициализируйте переменную shortestDistance = INT_MAX.

2️⃣Переберите индексы в списке indices1 и для каждого индекса найдите верхнюю границу в списке indices2, используя бинарный поиск, и сохраните этот индекс в переменную x. Рассмотрите индексы indices2[x] и indices2[x - 1], обновляя shortestDistance, если индексы не совпадают.

3️⃣Верните значение переменной shortestDistance.

😎 Решение:
package main

import (
"math"
"sort"
)

func shortestWordDistance(wordsDict []string, word1 string, word2 string) int {
var indices1, indices2 []int
for i, word := range wordsDict {
if word == word1 {
indices1 = append(indices1, i)
}
if word == word2 {
indices2 = append(indices2, i)
}
}

shortestDistance := math.MaxInt32
for _, index := range indices1 {
x := sort.Search(len(indices2), func(i int) bool { return indices2[i] > index })
if x < len(indices2) {
shortestDistance = min(shortestDistance, indices2[x]-index)
}
if x > 0 && indices2[x-1] != index {
shortestDistance = min(shortestDistance, index-indices2[x-1])
}
}
return shortestDistance
}

func min(a, b int) int {
if a < b {
return a
}
return b
}


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

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

Дана строка num, представляющая собой целое число. Верните true, если num является стробограмматическим числом.

Стробограмматическое число — это число, которое выглядит одинаково при повороте на 180 градусов (если посмотреть вверх ногами).

Пример:
Input: num = "69"
Output: true


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

1️⃣Создайте новую строку, перебирая оригинальную строку num в обратном порядке. Для каждого символа проверьте, является ли он допустимым для поворота (0, 1, 6, 8, 9). Если символ недопустим (2, 3, 4, 5, 7), немедленно верните false.

2️⃣Для каждого допустимого символа добавьте его соответствующее значение после поворота (0 ⟶ 0, 1 ⟶ 1, 6 ⟶ 9, 8 ⟶ 8, 9 ⟶ 6) в новую строку.

3️⃣Сравните полученную строку с исходной строкой num. Если они равны, верните true, в противном случае верните false.

😎 Решение:
func isStrobogrammatic(num string) bool {
rotated := ""
for i := len(num) - 1; i >= 0; i-- {
switch num[i] {
case '0', '1', '8':
rotated += string(num[i])
case '6':
rotated += "9"
case '9':
rotated += "6"
default:
return false
}
}
return num == rotated
}


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

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

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

Стробограмматическое число — это число, которое выглядит одинаково при повороте на 180 градусов (если посмотреть вверх ногами).

Пример:
Input: n = 2
Output: ["11","69","88","96"]


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

1️⃣Инициализируйте структуру данных reversiblePairs, которая содержит все пары обратимых цифр. Вызовите и верните результат рекурсивной функции generateStroboNumbers(n, finalLength), где первый аргумент указывает, что текущий вызов создаст все стробограмматические числа длиной n, а второй аргумент указывает длину конечных стробограмматических чисел, которые мы будем генерировать, и будет использоваться для проверки возможности добавления '0' в начало и конец числа.

2️⃣Создайте функцию generateStroboNumbers(n, finalLength), которая вернет все стробограмматические числа длиной n:
Проверьте базовые случаи: если n == 0, верните массив с пустой строкой [""]; если n == 1, верните ["0", "1", "8"].
Вызовите generateStroboNumbers(n - 2, finalLength), чтобы получить все стробограмматические числа длиной (n-2), и сохраните их в subAns.
Инициализируйте пустой массив currStroboNums для хранения стробограмматических чисел длиной n.

3️⃣Для каждого числа в subAns добавьте все reversiblePairs в начало и конец, за исключением случая, когда текущая пара '00' и n == finalLength (потому что нельзя добавить '0' в начало числа), и добавьте это новое число в currStroboNums. В конце функции верните все стробограмматические числа, т.е. currStroboNums.

😎 Решение:
package main

func findStrobogrammatic(n int) []string {
reversiblePairs := [][]string{
{"0", "0"}, {"1", "1"},
{"6", "9"}, {"8", "8"}, {"9", "6"},
}

var generateStroboNumbers func(int, int) []string
generateStroboNumbers = func(n int, finalLength int) []string {
if n == 0 {
return []string{""}
}

if n == 1 {
return []string{"0", "1", "8"}
}

prevStroboNums := generateStroboNumbers(n-2, finalLength)
var currStroboNums []string

for _, prevStroboNum := range prevStroboNums {
for _, pair := range reversiblePairs {
if pair[0] != "0" || n != finalLength {
currStroboNums = append(currStroboNums, pair[0]+prevStroboNum+pair[1])
}
}
}

return currStroboNums
}

return generateStroboNumbers(n, n)
}


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
#medium
Задача: 249. Group Shifted Strings

Выполните следующие операции сдвига на строке:

Правый сдвиг: замените каждую букву следующей буквой английского алфавита, где 'z' заменяется на 'a'. Например, "abc" можно сдвинуть вправо на "bcd" или "xyz" можно сдвинуть вправо на "yza".
Левый сдвиг: замените каждую букву предыдущей буквой английского алфавита, где 'a' заменяется на 'z'. Например, "bcd" можно сдвинуть влево на "abc" или "yza" можно сдвинуть влево на "xyz".
Мы можем продолжать сдвигать строку в обоих направлениях, чтобы сформировать бесконечную последовательность сдвигов.

Например, сдвиньте "abc", чтобы сформировать последовательность: ... <-> "abc" <-> "bcd" <-> ... <-> "xyz" <-> "yza" <-> .... <-> "zab" <-> "abc" <-> ...
Вам дан массив строк strings, сгруппируйте все strings[i], которые принадлежат одной и той же последовательности сдвигов. Ответ можно вернуть в любом порядке.

Пример:
Input: strings = ["abc","bcd","acef","xyz","az","ba","a","z"]

Output: [["acef"],["a","z"],["abc","bcd","xyz"],["az","ba"]]


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

1️⃣Переберите строки, и для каждой строки найдите ее хэш-значение, сдвигая все символы так, чтобы строка начиналась с 'a'. Значение сдвига равно позиции первого символа строки, и каждый символ сдвигается на это значение с учетом модуля 26.

2️⃣Сопоставьте оригинальную строку с найденным хэш-значением в карте mapHashToList, добавляя оригинальную строку в список, соответствующий ее хэш-значению.

3️⃣Переберите mapHashToList и сохраните список для каждого ключа в карте в массив ответа groups.

😎 Решение:
package main

import (
"fmt"
"strings"
)

func shiftLetter(letter byte, shift int) byte {
return (letter - byte(shift) + 26) % 26 + 'a'
}

func getHash(s string) string {
shift := s[0] - 'a'
var hashKey strings.Builder

for i := 0; i < len(s); i++ {
hashKey.WriteByte(shiftLetter(s[i], int(shift)))
}

return hashKey.String()
}

func groupStrings(strings []string) [][]string {
mapHashToList := make(map[string][]string)

for _, str := range strings {
hashKey := getHash(str)
mapHashToList[hashKey] = append(mapHashToList[hashKey], str)
}

groups := [][]string{}
for _, v := range mapHashToList {
groups = append(groups, v)
}

return groups
}

func main() {
strings := []string{"abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"}
result := groupStrings(strings)
fmt.Println(result)
}


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
#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.

😎 Решение:
package main

type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}

type Solution struct {
count int
}

func (s *Solution) dfs(node *TreeNode) bool {
if node == nil {
return true
}

isLeftUniValue := s.dfs(node.Left)
isRightUniValue := s.dfs(node.Right)

if isLeftUniValue && isRightUniValue {
if node.Left != nil && node.Left.Val != node.Val {
return false
}
if node.Right != nil && node.Right.Val != node.Val {
return false
}
s.count++
return true
}
return false
}

func (s *Solution) CountUnivalSubtrees(root *TreeNode) int {
s.dfs(root)
return s.count
}


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

🔒 База собесов | 🔒 База тестовых
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 нечетная, сохраняем символ, который встречается нечетное количество раз, отдельно.

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

😎 Решение:
package main

import (
"fmt"
"strings"
)

type Solution struct {
set map[string]struct{}
}

func NewSolution() *Solution {
return &Solution{set: make(map[string]struct{})}
}

func (sol *Solution) generatePalindromes(s string) []string {
mapChars := make([]int, 128)
st := make([]rune, len(s)/2)
if !sol.canPermutePalindrome(s, mapChars) {
return []string{}
}

var ch rune
k := 0
for i := 0; i < len(mapChars); i++ {
if mapChars[i]%2 == 1 {
ch = rune(i)
}
for j := 0; j < mapChars[i]/2; j++ {
st[k] = rune(i)
k++
}
}
sol.permute(st, 0, ch)
result := []string{}
for key := range sol.set {
result = append(result, key)
}
return result
}

func (sol *Solution) canPermutePalindrome(s string, mapChars []int) bool {
count := 0
for _, char := range s {
index := int(char)
mapChars[index]++
if mapChars[index]%2 == 0 {
count--
} else {
count++
}
}
return count <= 1
}

func (sol *Solution) swap(s []rune, i, j int) {
s[i], s[j] = s[j], s[i]
}

func (sol *Solution) permute(s []rune, l int, ch rune) {
if l == len(s) {
var sb strings.Builder
sb.WriteString(string(s))
if ch != 0 {
sb.WriteRune(ch)
}
for i := len(s) - 1; i >= 0; i-- {
sb.WriteRune(s[i])
}
sol.set[sb.String()] = struct{}{}
} else {
for i := l; i < len(s); i++ {
if s[l] != s[i] || l == i {
sol.swap(s, l, i)
sol.permute(s, l+1, ch)
sol.swap(s, l, i)
}
}
}
}


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

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🤔1
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Golang | LeetCode pinned «👾 349 вопросов собесов на Golang Developer 🔒 База реальных собесов 🔒 База тестовых заданий 👾 Список менторов 👣 Golang ├ Вопросы собесов ├ Вакансии └ Тесты 👩‍💻 С/С++ ├ Вопросы собесов ├ Вакансии ├ LeetCode ответы └ Тесты 👩‍💻 PHP ├ Вопросы собесов ├ Вакансии…»
#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().

😎 Решение:
type Vector2D struct {
nums []int
position int
}

func Constructor(v [][]int) Vector2D {
nums := make([]int, 0)
for _, innerList := range v {
nums = append(nums, innerList...)
}
return Vector2D{nums, -1}
}

func (this *Vector2D) Next() int {
this.position++
return this.nums[this.position]
}

func (this *Vector2D) HasNext() bool {
return this.position + 1 < len(this.nums)
}


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

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