#medium
Задача: 445. Add Two Numbers II
Вам даны два непустых связанных списка, представляющих два неотрицательных целых числа. Самый значимый разряд стоит первым, и каждый из их узлов содержит одну цифру. Сложите два числа и верните сумму в виде связанного списка.
Вы можете предположить, что оба числа не содержат начальных нулей, за исключением самого числа 0.
Пример:
👨💻 Алгоритм:
1⃣ Создайте два связанных списка r1 и r2, чтобы хранить перевернутые связанные списки l1 и l2 соответственно. Создайте два целых числа totalSum и carry для хранения суммы и переноса текущих цифр. Создайте новый ListNode, ans, который будет хранить сумму текущих цифр. Мы будем складывать два числа, используя перевернутый список, добавляя цифры по одной. Продолжаем, пока не пройдем все узлы в r1 и r2.
2⃣ Если r1 не равен null, добавляем r1.val к totalSum. Если r2 не равен null, добавляем r2.val к totalSum. Устанавливаем ans.val = totalSum % 10. Сохраняем перенос как totalSum / 10. Создаем новый ListNode, newNode, который будет иметь значение как перенос. Устанавливаем next для newNode как ans. Обновляем ans = newNode, чтобы использовать ту же переменную ans для следующей итерации. Обновляем totalSum = carry.
3⃣ Если carry == 0, это означает, что newNode, созданный в финальной итерации цикла while, имеет значение 0. Поскольку мы выполняем ans = newNode в конце каждой итерации цикла while, чтобы избежать возврата связанного списка с головой, равной 0 (начальный ноль), возвращаем следующий элемент, т.е. возвращаем ans.next. В противном случае, если перенос не равен 0, значение ans не равно нулю. Следовательно, просто возвращаем ans.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 445. Add Two Numbers II
Вам даны два непустых связанных списка, представляющих два неотрицательных целых числа. Самый значимый разряд стоит первым, и каждый из их узлов содержит одну цифру. Сложите два числа и верните сумму в виде связанного списка.
Вы можете предположить, что оба числа не содержат начальных нулей, за исключением самого числа 0.
Пример:
Input: l1 = [7,2,4,3], l2 = [5,6,4]
Output: [7,8,0,7]
type ListNode struct {
Val int
Next *ListNode
}
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
var temp *ListNode
for head != nil {
temp = head.Next
head.Next = prev
prev = head
head = temp
}
return prev
}
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
r1 := reverseList(l1)
r2 := reverseList(l2)
totalSum := 0
carry := 0
ans := &ListNode{}
for r1 != nil || r2 != nil {
if r1 != nil {
totalSum += r1.Val
r1 = r1.Next
}
if r2 != nil {
totalSum += r2.Val
r2 = r2.Next
}
ans.Val = totalSum % 10
carry = totalSum / 10
head := &ListNode{Val: carry}
head.Next = ans
ans = head
totalSum = carry
}
if carry == 0 {
return ans.Next
}
return ans
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 446. Arithmetic Slices II - Subsequence
Дан целочисленный массив nums, вернуть количество всех арифметических подпоследовательностей nums.
Последовательность чисел называется арифметической, если она состоит как минимум из трех элементов и если разница между любыми двумя последовательными элементами одинаковая.
Например, [1, 3, 5, 7, 9], [7, 7, 7, 7] и [3, -1, -5, -9] являются арифметическими последовательностями.
Например, [1, 1, 2, 5, 7] не является арифметической последовательностью.
Подпоследовательность массива - это последовательность, которая может быть образована путем удаления некоторых элементов (возможно, ни одного) из массива.
Например, [2, 5, 10] является подпоследовательностью [1, 2, 1, 2, 4, 1, 5, 10].
Тестовые случаи сгенерированы таким образом, что ответ помещается в 32-битное целое число.
Пример:
👨💻 Алгоритм:
1⃣ Мы можем использовать поиск в глубину (DFS) для генерации всех подпоследовательностей.
2⃣ Мы можем проверить, является ли подпоследовательность арифметической, согласно ее определению.
3⃣ Возвращаем количество всех арифметических подпоследовательностей.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 446. Arithmetic Slices II - Subsequence
Дан целочисленный массив nums, вернуть количество всех арифметических подпоследовательностей nums.
Последовательность чисел называется арифметической, если она состоит как минимум из трех элементов и если разница между любыми двумя последовательными элементами одинаковая.
Например, [1, 3, 5, 7, 9], [7, 7, 7, 7] и [3, -1, -5, -9] являются арифметическими последовательностями.
Например, [1, 1, 2, 5, 7] не является арифметической последовательностью.
Подпоследовательность массива - это последовательность, которая может быть образована путем удаления некоторых элементов (возможно, ни одного) из массива.
Например, [2, 5, 10] является подпоследовательностью [1, 2, 1, 2, 4, 1, 5, 10].
Тестовые случаи сгенерированы таким образом, что ответ помещается в 32-битное целое число.
Пример:
Input: nums = [2,4,6,8,10]
Output: 7
Explanation: All arithmetic subsequence slices are:
[2,4,6]
[4,6,8]
[6,8,10]
[2,4,6,8]
[4,6,8,10]
[2,4,6,8,10]
[2,6,10]
type Solution struct {
n int
ans int
}
func (sol *Solution) dfs(dep int, A []int, cur []int64) {
if dep == sol.n {
if len(cur) < 3 {
return
}
for i := 1; i < len(cur); i++ {
if cur[i]-cur[i-1] != cur[1]-cur[0] {
return
}
}
sol.ans++
return
}
sol.dfs(dep+1, A, cur)
cur = append(cur, int64(A[dep]))
sol.dfs(dep+1, A, cur)
cur = cur[:len(cur)-1]
}
func numberOfArithmeticSlices(A []int) int {
sol := Solution{n: len(A), ans: 0}
sol.dfs(0, A, []int64{})
return sol.ans
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Привет, ребята!
1,5 года я учился на программиста, а сайт easyoffer.ru стал моим пет-проектом. Я создавал его, потому что:
а) нужно было добавить хоть какой-нибудь проект в резюме
б) подготовиться к прохождению собесов
И всё получилось! Благодаря еasyoffer я успешно прошёл собеседование и устроился Python Junior-разработчиком на удаленку с зарплатой 115 тысяч рублей.
Однако ещё во время разработки я понял, что у этого проекта есть потенциал. Казалось, что сайт может стать популярным и, возможно, превратиться в стартап.
По-этому я с самого начала заложил в проект минимальную бизнес-модель, на случай, если сайт начнёт набирать трафик. Я предложил пользователям полный доступ к сайту в обмен на подписку на Telegram-каналы. Это позволяло развивать аудиторию, а в будущем — зарабатывать на рекламе.
Результат превзошёл ожидания!
С момента запуска easyoffer посетило 400 тысяч человек. А когда доход с рекламы превысил мою зарплату программиста, я принял решение уйти с работы и полностью посвятить себя разработке новой версии сайта.
Вот так, зайдя в IT, через 4 месяца вышел через свой же пет-проект. Мне очень повезло
Уже год я работаю над easyoffer 2.0.
Это будет более масштабный и качественной новый проект:
– Появится тренажер
– Появятся задачи из собесов
– Фильтрация контента по грейдам
и еще очень много фич, о которых я расскажу позже.
Хочу, довести easyoffer до ума, чтобы сайт стал настоящим помощником для всех, кто готовится к собеседованиям.
По этому в ближайшее время я объявлю о старте краудфандинговой кампании, чтобы ускорить разработку и я готов щедро отблагодарить всех, кто поддержит проект.
А те, кто поддержат проект первыми, получат специальные лимитированные выгодные вознаграждения. Следите за этим телеграм каналом, если хотите стать первыми сапортерами.
1,5 года я учился на программиста, а сайт easyoffer.ru стал моим пет-проектом. Я создавал его, потому что:
а) нужно было добавить хоть какой-нибудь проект в резюме
б) подготовиться к прохождению собесов
И всё получилось! Благодаря еasyoffer я успешно прошёл собеседование и устроился Python Junior-разработчиком на удаленку с зарплатой 115 тысяч рублей.
Однако ещё во время разработки я понял, что у этого проекта есть потенциал. Казалось, что сайт может стать популярным и, возможно, превратиться в стартап.
По-этому я с самого начала заложил в проект минимальную бизнес-модель, на случай, если сайт начнёт набирать трафик. Я предложил пользователям полный доступ к сайту в обмен на подписку на Telegram-каналы. Это позволяло развивать аудиторию, а в будущем — зарабатывать на рекламе.
Результат превзошёл ожидания!
С момента запуска easyoffer посетило 400 тысяч человек. А когда доход с рекламы превысил мою зарплату программиста, я принял решение уйти с работы и полностью посвятить себя разработке новой версии сайта.
Вот так, зайдя в IT, через 4 месяца вышел через свой же пет-проект. Мне очень повезло
Уже год я работаю над easyoffer 2.0.
Это будет более масштабный и качественной новый проект:
– Появится тренажер
– Появятся задачи из собесов
– Фильтрация контента по грейдам
и еще очень много фич, о которых я расскажу позже.
Хочу, довести easyoffer до ума, чтобы сайт стал настоящим помощником для всех, кто готовится к собеседованиям.
По этому в ближайшее время я объявлю о старте краудфандинговой кампании, чтобы ускорить разработку и я готов щедро отблагодарить всех, кто поддержит проект.
А те, кто поддержат проект первыми, получат специальные лимитированные выгодные вознаграждения. Следите за этим телеграм каналом, если хотите стать первыми сапортерами.
#medium
Задача: 364. Nested List Weight Sum II
Вам дан вложенный список целых чисел nestedList. Каждый элемент является либо целым числом, либо списком, элементы которого также могут быть целыми числами или другими списками.
Глубина целого числа — это количество списков, внутри которых оно находится. Например, вложенный список [1,[2,2],[[3],2],1] имеет значение каждого целого числа, установленное равным его глубине. Пусть maxDepth будет максимальной глубиной любого целого числа.
Вес целого числа определяется как maxDepth - (глубина целого числа) + 1.
Верните сумму каждого целого числа в nestedList, умноженную на его вес.
Пример:
👨💻 Алгоритм:
1⃣ Инициализировать первый уровень BFS-дерева, добавив все элементы из входного nestedList в очередь.
2⃣ Для каждого уровня извлекать передний элемент из очереди. Если это список, то добавить его элементы в очередь. В противном случае обновить значения sumOfElements, maxDepth и sumOfProducts.
3⃣ Когда очередь станет пустой, вернуть значение (maxDepth + 1) * sumOfElements - sumOfProducts.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 364. Nested List Weight Sum II
Вам дан вложенный список целых чисел nestedList. Каждый элемент является либо целым числом, либо списком, элементы которого также могут быть целыми числами или другими списками.
Глубина целого числа — это количество списков, внутри которых оно находится. Например, вложенный список [1,[2,2],[[3],2],1] имеет значение каждого целого числа, установленное равным его глубине. Пусть maxDepth будет максимальной глубиной любого целого числа.
Вес целого числа определяется как maxDepth - (глубина целого числа) + 1.
Верните сумму каждого целого числа в nestedList, умноженную на его вес.
Пример:
Input: nestedList = [[1,1],2,[1,1]]
Output: 8
Explanation: Four 1's with a weight of 1, one 2 with a weight of 2.
1*1 + 1*1 + 2*2 + 1*1 + 1*1 = 8
package main
type NestedInteger struct {
// This is a placeholder structure for the NestedInteger implementation
}
func (ni NestedInteger) IsInteger() bool {
// Placeholder method
return false
}
func (ni NestedInteger) GetInteger() int {
// Placeholder method
return 0
}
func (ni NestedInteger) GetList() []*NestedInteger {
// Placeholder method
return nil
}
func depthSumInverse(nestedList []*NestedInteger) int {
queue := append([]*NestedInteger(nil), nestedList...)
depth, maxDepth, sumOfElements, sumOfProducts := 1, 0, 0, 0
for len(queue) > 0 {
size := len(queue)
if depth > maxDepth {
maxDepth = depth
}
for i := 0; i < size; i++ {
nested := queue[0]
queue = queue[1:]
if nested.IsInteger() {
value := nested.GetInteger()
sumOfElements += value
sumOfProducts += value * depth
} else {
queue = append(queue, nested.GetList()...)
}
}
depth++
}
return (maxDepth + 1) * sumOfElements - sumOfProducts
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 366. Find Leaves of Binary Tree
Дан корень бинарного дерева, соберите узлы дерева следующим образом:
Соберите все листовые узлы.
Удалите все листовые узлы.
Повторяйте, пока дерево не станет пустым.
Пример:
👨💻 Алгоритм:
1⃣ Реализовать функцию getHeight(node), которая будет вычислять высоту каждого узла в дереве с использованием рекурсивного обхода в глубину (post-order). Если узел является null, вернуть -1.
2⃣ Сохранить пары (высота, значение) для всех узлов и отсортировать их по высоте.
3⃣ Организовать узлы по высоте и вернуть результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 366. Find Leaves of Binary Tree
Дан корень бинарного дерева, соберите узлы дерева следующим образом:
Соберите все листовые узлы.
Удалите все листовые узлы.
Повторяйте, пока дерево не станет пустым.
Пример:
Input: root = [1,2,3,4,5]
Output: [[4,5,3],[2],[1]]
Explanation:
[[3,5,4],[2],[1]] and [[3,4,5],[2],[1]] are also considered correct answers since per each level it does not matter the order on which elements are returned.
package main
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
type pair struct {
height, value int
}
type Solution struct {
pairs []pair
}
func (s *Solution) getHeight(node *TreeNode) int {
if node == nil {
return -1
}
leftHeight := s.getHeight(node.Left)
rightHeight := s.getHeight(node.Right)
currHeight := max(leftHeight, rightHeight) + 1
s.pairs = append(s.pairs, pair{currHeight, node.Val})
return currHeight
}
func (s *Solution) findLeaves(root *TreeNode) [][]int {
s.getHeight(root)
sort.Slice(s.pairs, func(i, j int) bool {
return s.pairs[i].height < s.pairs[j].height
})
var solution [][]int
currentHeight := -1
for _, p := range s.pairs {
if p.height != currentHeight {
solution = append(solution, []int{})
currentHeight = p.height
}
solution[len(solution)-1] = append(solution[len(solution)-1], p.value)
}
return solution
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 591. Tag Validator
Дана строка, представляющая фрагмент кода, реализуйте валидатор тегов для разбора кода и определения его корректности.
Фрагмент кода считается корректным, если соблюдаются все следующие правила:
Код должен быть заключен в корректный закрытый тег. В противном случае код некорректен.
Закрытый тег (не обязательно корректный) имеет точно следующий формат: <TAG_NAME>TAG_CONTENT</TAG_NAME>. Среди них <TAG_NAME> — это начальный тег, а </TAG_NAME> — конечный тег. TAG_NAME в начальном и конечном тегах должен быть одинаковым. Закрытый тег корректен, если и только если TAG_NAME и TAG_CONTENT корректны.
Корректное TAG_NAME содержит только заглавные буквы и имеет длину в диапазоне [1, 9]. В противном случае TAG_NAME некорректен.
Корректное TAG_CONTENT может содержать другие корректные закрытые теги, cdata и любые символы (см. примечание 1), КРОМЕ неподходящих <, неподходящих начальных и конечных тегов, и неподходящих или закрытых тегов с некорректным TAG_NAME. В противном случае TAG_CONTENT некорректен.
Начальный тег неподходящий, если нет конечного тега с тем же TAG_NAME, и наоборот. Однако нужно также учитывать проблему несбалансированных тегов, когда они вложены.
< неподходящий, если не удается найти последующий >. И когда вы находите < или </, все последующие символы до следующего > должны быть разобраны как TAG_NAME (не обязательно корректный).
cdata имеет следующий формат: <![CDATA[CDATA_CONTENT]]>. Диапазон CDATA_CONTENT определяется как символы между <![CDATA[ и первым последующим ]]>.
CDATA_CONTENT может содержать любые символы. Функция cdata заключается в том, чтобы запретить валидатору разбирать CDATA_CONTENT, поэтому даже если в нем есть символы, которые могут быть разобраны как тег (корректный или некорректный), вы должны рассматривать их как обычные символы.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте стек для отслеживания открытых тегов и флаг для определения наличия тегов. Используйте регулярное выражение для проверки корректности TAG_NAME, TAG_CONTENT и CDATA.
2⃣ Пройдитесь по строке, проверяя каждый символ. Если встретите <, определите тип тега (начальный, конечный или CDATA). Обновите стек и индексы в зависимости от найденного типа.
3⃣ В конце проверьте, что стек пуст (все теги корректно закрыты) и верните результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 591. Tag Validator
Дана строка, представляющая фрагмент кода, реализуйте валидатор тегов для разбора кода и определения его корректности.
Фрагмент кода считается корректным, если соблюдаются все следующие правила:
Код должен быть заключен в корректный закрытый тег. В противном случае код некорректен.
Закрытый тег (не обязательно корректный) имеет точно следующий формат: <TAG_NAME>TAG_CONTENT</TAG_NAME>. Среди них <TAG_NAME> — это начальный тег, а </TAG_NAME> — конечный тег. TAG_NAME в начальном и конечном тегах должен быть одинаковым. Закрытый тег корректен, если и только если TAG_NAME и TAG_CONTENT корректны.
Корректное TAG_NAME содержит только заглавные буквы и имеет длину в диапазоне [1, 9]. В противном случае TAG_NAME некорректен.
Корректное TAG_CONTENT может содержать другие корректные закрытые теги, cdata и любые символы (см. примечание 1), КРОМЕ неподходящих <, неподходящих начальных и конечных тегов, и неподходящих или закрытых тегов с некорректным TAG_NAME. В противном случае TAG_CONTENT некорректен.
Начальный тег неподходящий, если нет конечного тега с тем же TAG_NAME, и наоборот. Однако нужно также учитывать проблему несбалансированных тегов, когда они вложены.
< неподходящий, если не удается найти последующий >. И когда вы находите < или </, все последующие символы до следующего > должны быть разобраны как TAG_NAME (не обязательно корректный).
cdata имеет следующий формат: <![CDATA[CDATA_CONTENT]]>. Диапазон CDATA_CONTENT определяется как символы между <![CDATA[ и первым последующим ]]>.
CDATA_CONTENT может содержать любые символы. Функция cdata заключается в том, чтобы запретить валидатору разбирать CDATA_CONTENT, поэтому даже если в нем есть символы, которые могут быть разобраны как тег (корректный или некорректный), вы должны рассматривать их как обычные символы.
Пример:
Input: code = "<DIV>This is the first line <![CDATA[<div>]]></DIV>"
Output: true
package main
import (
"regexp"
"strings"
)
type Solution struct {
stack []string
containsTag bool
}
func (s *Solution) isValidTagName(tag string, ending bool) bool {
if ending {
if len(s.stack) > 0 && s.stack[len(s.stack)-1] == tag {
s.stack = s.stack[:len(s.stack)-1]
} else {
return false
}
} else {
s.containsTag = true
s.stack = append(s.stack, tag)
}
return true
}
func (s *Solution) IsValid(code string) bool {
regex := "<[A-Z]{0,9}>([^<]*(<((\\/?[A-Z]{1,9}>)|(!\\[CDATA\\[(.*?)]]>)))?)*"
matched, _ := regexp.MatchString(regex, code)
if !matched {
return false
}
for i := 0; i < len(code); i++ {
ending := false
if len(s.stack) == 0 && s.containsTag {
return false
}
if code[i] == '<' {
if code[i+1] == '!' {
i = strings.Index(code[i+1:], "]]>") + i + 2
if i == -1 {
return false
}
continue
}
if code[i+1] == '/' {
i++
ending = true
}
closeIndex := strings.Index(code[i+1:], ">") + i + 1
if closeIndex == -1 || !s.isValidTagName(code[i+1:closeIndex], ending) {
return false
}
i = closeIndex
}
}
return len(s.stack) == 0
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 764. Largest Plus Sign
Вам дано целое число n. У вас есть бинарная сетка размером n x n, в которой все значения изначально равны 1, за исключением некоторых индексов, указанных в массиве mines. Элемент массива mines с индексом i определяется как mines[i] = [xi, yi], где grid[xi][yi] == 0.
Верните порядок самого большого крестообразного знака из 1, выровненного по осям, который содержится в сетке. Если такого знака нет, верните 0.
Крестообразный знак из 1 порядка k имеет некоторый центр grid[r][c] == 1, а также четыре луча длиной k - 1, идущих вверх, вниз, влево и вправо, состоящие из 1. Обратите внимание, что за пределами лучей креста могут быть 0 или 1, проверяется только соответствующая область крестообразного знака на наличие 1.
Пример:
👨💻 Алгоритм:
1⃣ Создайте сетку размером n x n, заполненную единицами. Затем используйте массив mines, чтобы установить значения нулей в соответствующих ячейках сетки.
2⃣ Для каждой ячейки в сетке создайте четыре дополнительных сетки: left, right, up и down, которые будут хранить длину непрерывных единиц, простирающихся в соответствующем направлении от каждой ячейки.
3⃣ Пройдите по всей сетке и для каждой ячейки определите минимальную длину луча среди четырех направлений. Эта минимальная длина будет определять порядок крестообразного знака с центром в данной ячейке. Обновите максимальный порядок крестообразного знака и верните его после завершения обхода всей сетки. Если такого знака нет, верните 0.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 764. Largest Plus Sign
Вам дано целое число n. У вас есть бинарная сетка размером n x n, в которой все значения изначально равны 1, за исключением некоторых индексов, указанных в массиве mines. Элемент массива mines с индексом i определяется как mines[i] = [xi, yi], где grid[xi][yi] == 0.
Верните порядок самого большого крестообразного знака из 1, выровненного по осям, который содержится в сетке. Если такого знака нет, верните 0.
Крестообразный знак из 1 порядка k имеет некоторый центр grid[r][c] == 1, а также четыре луча длиной k - 1, идущих вверх, вниз, влево и вправо, состоящие из 1. Обратите внимание, что за пределами лучей креста могут быть 0 или 1, проверяется только соответствующая область крестообразного знака на наличие 1.
Пример:
Input: n = 5, mines = [[4,2]]
Output: 2
Explanation: In the above grid, the largest plus sign can only be of order 2. One of them is shown.
func orderOfLargestPlusSign(N int, mines [][]int) int {
banned := make(map[int]bool)
for _, mine := range mines {
banned[mine[0]*N + mine[1]] = true
}
ans := 0
for r := 0; r < N; r++ {
for c := 0; c < N; c++ {
k := 0
for k <= r && r < N - k && k <= c && c < N - k &&
!banned[(r - k) * N + c] &&
!banned[(r + k) * N + c] &&
!banned[r * N + c - k] &&
!banned[r * N + c + k] {
k++
}
if k > ans {
ans = k
}
}
}
return ans
}Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Ищу работу пол года
Практически под каждым постом в этом канале я вижу комментарии от людей, которые ищут работу по полгода. Это перерастает в обсуждение того, как нужно (или не нужно) искать работу, почему процесс найма сломан и как они откликались на фейковые вакансии.
Честно говоря, искать работу полгода — это нонсенс. Очевидно, что человек делает что-то не так. Главная ошибка, которую совершают многие, — это создание иллюзии поиска работы.
То есть человек вроде бы ищет работу, но делает это неэффективно, тратя время на нецелевые действия. Например:
➖ Просматривает вакансии перед откликом.
➖ Пытается понять, подходит ли он под вакансию. Если считает, что не подходит — не откликается.
➖ Пишет сопроводительные письма (иногда даже уникальные под каждую вакансию).
➖ Заполняет анкеты, проходит тесты.
Все эти действия отнимают время, но не приводят к результату.
Почему это не работает?
HR-менеджер не может вручную отсмотреть 2000 откликов, оценить каждое резюме и прочитать сопроводительные письма. Поэтому компании используют ATS-системы (системы автоматического подбора), которые анализируют резюме и определяют процент его соответствия вакансии.
Что делать, чтобы повысить шансы?
1️⃣ Добавить ключевые навыки в резюме — и в основной текст, и в теги. Возьмите их с easyoffer.ru
2️⃣ Убрать нерелевантный опыт, оставить только подходящий.
3️⃣ Оформить опыт так, чтобы он выглядел релевантным. Если у вас его нет, укажите проекты, стажировки или другой опыт, который можно представить как работу от 1 года. Если опыт слишком большой, сузьте его до 6 лет.
4️⃣ Откликаться на все вакансии без разбору. Если вы Junior, не ищите только стажер или Junior-вакансии — пробуйте везде. Не отказывайте себе сами, пусть это решит HR
5️⃣ Сделать резюме публичным, потому что HR-менеджеры часто ищут кандидатов не только среди откликов, но и в базе резюме.
6️⃣ Используйте ИИ по минимуму – ATS-системы считывают это и помечают "сгенерировано ИИ"
‼️ Главное правило: чем больше откликов — тем выше шанс получить оффер. Делайте резюме удобным для ATS-систем, и вас заметят.
1. Посмотрите видео о том как я вывел свою резюме в Топ1 на HH
2. Посмотрите видео как я нашел первую работу
3. Прочитайте этот кейс про оптимизацию резюме
Если прям вообще тяжело.
Создайте несколько разных резюме. Создайте 2, 3 да хоть 10 резюме. Настройте авто-отлики и ждите приглашения на собесы.
Не нужно создавать иллюзию поиска работы, сделайте несколько простых и актуальных действий.
Практически под каждым постом в этом канале я вижу комментарии от людей, которые ищут работу по полгода. Это перерастает в обсуждение того, как нужно (или не нужно) искать работу, почему процесс найма сломан и как они откликались на фейковые вакансии.
Честно говоря, искать работу полгода — это нонсенс. Очевидно, что человек делает что-то не так. Главная ошибка, которую совершают многие, — это создание иллюзии поиска работы.
То есть человек вроде бы ищет работу, но делает это неэффективно, тратя время на нецелевые действия. Например:
Все эти действия отнимают время, но не приводят к результату.
Почему это не работает?
HR-менеджер не может вручную отсмотреть 2000 откликов, оценить каждое резюме и прочитать сопроводительные письма. Поэтому компании используют ATS-системы (системы автоматического подбора), которые анализируют резюме и определяют процент его соответствия вакансии.
Что делать, чтобы повысить шансы?
1️⃣ Добавить ключевые навыки в резюме — и в основной текст, и в теги. Возьмите их с easyoffer.ru
2️⃣ Убрать нерелевантный опыт, оставить только подходящий.
3️⃣ Оформить опыт так, чтобы он выглядел релевантным. Если у вас его нет, укажите проекты, стажировки или другой опыт, который можно представить как работу от 1 года. Если опыт слишком большой, сузьте его до 6 лет.
4️⃣ Откликаться на все вакансии без разбору. Если вы Junior, не ищите только стажер или Junior-вакансии — пробуйте везде. Не отказывайте себе сами, пусть это решит HR
5️⃣ Сделать резюме публичным, потому что HR-менеджеры часто ищут кандидатов не только среди откликов, но и в базе резюме.
6️⃣ Используйте ИИ по минимуму – ATS-системы считывают это и помечают "сгенерировано ИИ"
‼️ Главное правило: чем больше откликов — тем выше шанс получить оффер. Делайте резюме удобным для ATS-систем, и вас заметят.
1. Посмотрите видео о том как я вывел свою резюме в Топ1 на HH
2. Посмотрите видео как я нашел первую работу
3. Прочитайте этот кейс про оптимизацию резюме
Если прям вообще тяжело.
Создайте несколько разных резюме. Создайте 2, 3 да хоть 10 резюме. Настройте авто-отлики и ждите приглашения на собесы.
Не нужно создавать иллюзию поиска работы, сделайте несколько простых и актуальных действий.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
#medium
Задача: 1514. Path with Maximum Probability
Вам дан неориентированный взвешенный граф из n узлов (индексация с нуля), представленный списком ребер, где edges[i] = [a, b] является неориентированным ребром, соединяющим узлы a и b с вероятностью успешного прохождения этого ребра succProb[i].
Даны два узла start и end, найдите путь с максимальной вероятностью успеха, чтобы перейти от start к end, и верните его вероятность успеха.
Если пути от start до end не существует, верните 0. Ваш ответ будет принят, если он отличается от правильного ответа не более чем на 1e-5.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте массив maxProb как максимальную вероятность достижения каждого узла из начального узла, установите maxProb[start] равным 1.
2⃣ Расслабьте все ребра: для каждого ребра (u, v), если найдена более высокая вероятность достижения u через это ребро, обновите max_prob[u] как max_prob[u] = max_prob[v] * path_prob. Если найдена более высокая вероятность достижения v через это ребро, обновите max_prob[v].
3⃣ Если нам не удается обновить какой-либо узел с более высокой вероятностью, мы можем остановить итерацию, перейдя к шагу 4. В противном случае повторяйте шаг 2, пока все ребра не будут расслаблены n - 1 раз. Верните max_prob[end].
😎 Решение🐍
Ставь 👍 и забирай 📚 Базу знаний
Задача: 1514. Path with Maximum Probability
Вам дан неориентированный взвешенный граф из n узлов (индексация с нуля), представленный списком ребер, где edges[i] = [a, b] является неориентированным ребром, соединяющим узлы a и b с вероятностью успешного прохождения этого ребра succProb[i].
Даны два узла start и end, найдите путь с максимальной вероятностью успеха, чтобы перейти от start к end, и верните его вероятность успеха.
Если пути от start до end не существует, верните 0. Ваш ответ будет принят, если он отличается от правильного ответа не более чем на 1e-5.
Пример:
Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
Output: 0.25000
Explanation: There are two paths from start to end, one having a probability of success = 0.2 and the other has 0.5 * 0.5 = 0.25.
func maxProbability(n int, edges [][]int, succProb []float64, start int, end int) float64 {
maxProb := make([]float64, n)
maxProb[start] = 1.0
for i := 0; i < n-1; i++ {
hasUpdate := false
for j := 0; j < len(edges); j++ {
u, v := edges[j][0], edges[j][1]
pathProb := succProb[j]
if maxProb[u]*pathProb > maxProb[v] {
maxProb[v] = maxProb[u] * pathProb
hasUpdate = true
}
if maxProb[v]*pathProb > maxProb[u] {
maxProb[u] = maxProb[v] * pathProb
hasUpdate = true
}
}
if !hasUpdate {
break
}
}
return maxProb[end]
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 710. Random Pick with Blacklist
Вам дано целое число n и массив уникальных целых чисел blacklist. Разработайте алгоритм выбора случайного целого числа из диапазона [0, n - 1], не входящего в черный список. Любое целое число, находящееся в указанном диапазоне и не входящее в черный список, должно с равной вероятностью быть возвращено. Оптимизируйте алгоритм так, чтобы он минимизировал количество обращений к встроенной функции random вашего языка. Реализуйте класс Solution: Solution(int n, int[] blacklist) Инициализирует объект целым числом n и целым числом из черного списка blacklist. int pick() Возвращает случайное целое число в диапазоне [0, n - 1] и не входящее в черный список.
Пример:
👨💻 Алгоритм:
1⃣ Создайте маппинг для чисел, входящих в черный список, чтобы сопоставить их с числами из диапазона [n - len(blacklist), n - 1], которые не входят в черный список.
2⃣ Создайте массив для хранения возможных чисел для выбора, исключая числа из черного списка.
3⃣ При каждом вызове функции pick() используйте встроенную функцию random для выбора случайного индекса из массива возможных чисел и возвращайте соответствующее значение.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 710. Random Pick with Blacklist
Вам дано целое число n и массив уникальных целых чисел blacklist. Разработайте алгоритм выбора случайного целого числа из диапазона [0, n - 1], не входящего в черный список. Любое целое число, находящееся в указанном диапазоне и не входящее в черный список, должно с равной вероятностью быть возвращено. Оптимизируйте алгоритм так, чтобы он минимизировал количество обращений к встроенной функции random вашего языка. Реализуйте класс Solution: Solution(int n, int[] blacklist) Инициализирует объект целым числом n и целым числом из черного списка blacklist. int pick() Возвращает случайное целое число в диапазоне [0, n - 1] и не входящее в черный список.
Пример:
Input
["Solution", "pick", "pick", "pick", "pick", "pick", "pick", "pick"]
[[7, [2, 3, 5]], [], [], [], [], [], [], []]
Output
[null, 0, 4, 1, 6, 1, 0, 4]
package main
import (
"math/rand"
"time"
)
type Solution struct {
mapping map[int]int
bound int
}
func Constructor(n int, blacklist []int) Solution {
mapping := make(map[int]int)
bound := n - len(blacklist)
blackset := make(map[int]struct{})
for _, b := range blacklist {
blackset[b] = struct{}{}
}
whitelist := bound
for _, b := range blacklist {
if b < bound {
for {
if _, exists := blackset[whitelist]; !exists {
break
}
whitelist++
}
mapping[b] = whitelist
whitelist++
}
}
return Solution{mapping: mapping, bound: bound}
}
func (this *Solution) Pick() int {
r := rand.Intn(this.bound)
if mapped, exists := this.mapping[r]; exists {
return mapped
}
return r
}
func main() {
rand.Seed(time.Now().UnixNano())
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 765. Couples Holding Hands
Есть n пар, сидящих на 2n местах, расположенных в ряд, и они хотят держаться за руки.
Люди и места представлены массивом целых чисел row, где row[i] — это ID человека, сидящего на i-м месте. Пары пронумерованы по порядку: первая пара — (0, 1), вторая пара — (2, 3) и так далее, до последней пары — (2n - 2, 2n - 1).
Верните минимальное количество перестановок, чтобы каждая пара сидела рядом. Перестановка состоит из выбора любых двух человек, которые встают и меняются местами.
Пример:
👨💻 Алгоритм:
1⃣ Мы могли бы предположить без доказательства, что решение, при котором мы делаем людей на каждом диване счастливыми по порядку, является оптимальным. Это предположение сильнее, чем гипотеза о жадном подходе, но кажется разумным, поскольку при каждом ходе мы делаем хотя бы одну пару счастливой.
2⃣ При таком предположении, для какого-то дивана с несчастливыми людьми X и Y, мы либо заменяем Y на партнера X, либо заменяем X на партнера Y. Для каждой из двух возможностей мы можем попробовать оба варианта, используя подход с возвратом.
3⃣ Для каждого дивана с двумя возможностями (т.е. оба человека на диване несчастливы) мы попробуем первый вариант, найдем ответ как ans1, затем отменим наш ход и попробуем второй вариант, найдем связанный ответ как ans2, отменим наш ход и затем вернем наименьший ответ.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 765. Couples Holding Hands
Есть n пар, сидящих на 2n местах, расположенных в ряд, и они хотят держаться за руки.
Люди и места представлены массивом целых чисел row, где row[i] — это ID человека, сидящего на i-м месте. Пары пронумерованы по порядку: первая пара — (0, 1), вторая пара — (2, 3) и так далее, до последней пары — (2n - 2, 2n - 1).
Верните минимальное количество перестановок, чтобы каждая пара сидела рядом. Перестановка состоит из выбора любых двух человек, которые встают и меняются местами.
Пример:
Input: row = [0,2,1,3]
Output: 1
Explanation: We only need to swap the second (row[1]) and third (row[2]) person.
type Solution struct {
N int
pairs [][]int
}
func (s *Solution) minSwapsCouples(row []int) int {
s.N = len(row) / 2
s.pairs = make([][]int, s.N)
for i := 0; i < s.N; i++ {
s.pairs[i] = []int{row[2*i] / 2, row[2*i+1] / 2}
}
return s.solve(0)
}
func (s *Solution) swap(a, b, c, d int) {
t := s.pairs[a][b]
s.pairs[a][b] = s.pairs[c][d]
s.pairs[c][d] = t
}
func (s *Solution) solve(i int) int {
if i == s.N {
return 0
}
x, y := s.pairs[i][0], s.pairs[i][1]
if x == y {
return s.solve(i + 1)
}
var jx, kx, jy, ky int
for j := i + 1; j < s.N; j++ {
for k := 0; k <= 1; k++ {
if s.pairs[j][k] == x {
jx, kx = j, k
}
if s.pairs[j][k] == y {
jy, ky = j, k
}
}
}
s.swap(i, 1, jx, kx)
ans1 := 1 + s.solve(i+1)
s.swap(i, 1, jx, kx)
s.swap(i, 0, jy, ky)
ans2 := 1 + s.solve(i+1)
s.swap(i, 0, jy, ky)
if ans1 < ans2 {
return ans1
}
return ans2
}Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 711. Number of Distinct Islands II
Вам дана двоичная матричная сетка m x n. Остров - это группа 1 (представляющая сушу), соединенных в четырех направлениях (горизонтальном или вертикальном). Можно предположить, что все четыре края сетки окружены водой. Остров считается одинаковым с другим, если они имеют одинаковую форму, или имеют одинаковую форму после поворота (только на 90, 180 или 270 градусов) или отражения (влево/вправо или вверх/вниз). Верните количество разных островов.
Пример:
👨💻 Алгоритм:
1⃣ Пройдите по каждому элементу матрицы, если найдена земля (1), выполните DFS для обнаружения всех связанных с этим островом земель и сохраните форму острова.
2⃣ Нормализуйте форму острова, применив все возможные повороты и отражения, чтобы найти каноническую форму.
3⃣ Используйте множество для хранения всех уникальных канонических форм и верните размер этого множества.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 711. Number of Distinct Islands II
Вам дана двоичная матричная сетка m x n. Остров - это группа 1 (представляющая сушу), соединенных в четырех направлениях (горизонтальном или вертикальном). Можно предположить, что все четыре края сетки окружены водой. Остров считается одинаковым с другим, если они имеют одинаковую форму, или имеют одинаковую форму после поворота (только на 90, 180 или 270 градусов) или отражения (влево/вправо или вверх/вниз). Верните количество разных островов.
Пример:
Input: grid = [[1,1,0,0,0],[1,0,0,0,0],[0,0,0,0,1],[0,0,0,1,1]]
Output: 1
package main
import (
"sort"
"strconv"
"strings"
)
func numDistinctIslands2(grid [][]int) int {
uniqueIslands := make(map[string]struct{})
for i := 0; i < len(grid); i++ {
for j := 0; j < len(grid[0]); j++ {
if grid[i][j] == 1 {
shape := [][]int{}
dfs(grid, i, j, i, j, &shape)
uniqueIslands[normalize(shape)] = struct{}{}
}
}
}
return len(uniqueIslands)
}
func dfs(grid [][]int, i, j, baseI, baseJ int, shape *[][]int) {
if i < 0 || i >= len(grid) || j < 0 || j >= len(grid[0]) || grid[i][j] == 0 {
return
}
grid[i][j] = 0
*shape = append(*shape, []int{i - baseI, j - baseJ})
dfs(grid, i+1, j, baseI, baseJ, shape)
dfs(grid, i-1, j, baseI, baseJ, shape)
dfs(grid, i, j+1, baseI, baseJ, shape)
dfs(grid, i, j-1, baseI, baseJ, shape)
}
func normalize(shape [][]int) string {
shapes := make([][][]int, 8)
for i := range shapes {
shapes[i] = [][]int{}
}
for _, p := range shape {
x, y := p[0], p[1]
shapes[0] = append(shapes[0], []int{x, y})
shapes[1] = append(shapes[1], []int{x, -y})
shapes[2] = append(shapes[2], []int{-x, y})
shapes[3] = append(shapes[3], []int{-x, -y})
shapes[4] = append(shapes[4], []int{y, x})
shapes[5] = append(shapes[5], []int{y, -x})
shapes[6] = append(shapes[6], []int{-y, x})
shapes[7] = append(shapes[7], []int{-y, -x})
}
for i := range shapes {
sort.Slice(shapes[i], func(a, b int) bool {
if shapes[i][a][0] == shapes[i][b][0] {
return shapes[i][a][1] < shapes[i][b][1]
}
return shapes[i][a][0] < shapes[i][b][0]
})
}
minShape := shapeToString(shapes[0])
for _, s := range shapes {
shapeStr := shapeToString(s)
if shapeStr < minShape {
minShape = shapeStr
}
}
return minShape
}
func shapeToString(shape [][]int) string {
var sb strings.Builder
for _, p := range shape {
sb.WriteString(strconv.Itoa(p[0]))
sb.WriteString(",")
sb.WriteString(strconv.Itoa(p[1]))
sb.WriteString(";")
}
return sb.String()
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#easy
Задача: 766. Toeplitz Matrix
Дана матрица размером m x n. Вернуть true, если матрица является Тёплицевой. В противном случае вернуть false.
Матрица является Тёплицевой, если все диагонали, идущие от верхнего левого к нижнему правому углу, содержат одинаковые элементы.
Пример:
👨💻 Алгоритм:
1⃣ Что отличает две координаты (r1, c1) и (r2, c2) на одной диагонали? Оказывается, две координаты находятся на одной диагонали тогда и только тогда, когда r1 - c1 == r2 - c2.м
2⃣ Это приводит к следующей идее: запоминайте значение этой диагонали как groups[r - c]. Если обнаружено несоответствие, то матрица не является Тёплицевой; в противном случае, она является таковой.
3⃣ Таким образом, для каждой ячейки матрицы сохраняйте значение диагонали в словаре groups с ключом r - c. Проходите по всем ячейкам матрицы и проверяйте, совпадает ли текущее значение с сохранённым в groups. Если где-то обнаруживается несоответствие, верните false. Если все элементы соответствуют, верните true.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 766. Toeplitz Matrix
Дана матрица размером m x n. Вернуть true, если матрица является Тёплицевой. В противном случае вернуть false.
Матрица является Тёплицевой, если все диагонали, идущие от верхнего левого к нижнему правому углу, содержат одинаковые элементы.
Пример:
Input: matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]]
Output: true
Explanation:
In the above grid, the diagonals are:
"[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]".
In each diagonal all elements are the same, so the answer is True.
func isToeplitzMatrix(matrix [][]int) bool {
groups := make(map[int]int)
for r := 0; r < len(matrix); r++ {
for c := 0; c < len(matrix[0]); c++ {
if _, ok := groups[r-c]; !ok {
groups[r-c] = matrix[r][c]
} else if groups[r-c] != matrix[r][c] {
return false
}
}
}
return true
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 712. Minimum ASCII Delete Sum for Two Strings
Если даны две строки s1 и s2, верните наименьшую ASCII-сумму удаленных символов, чтобы сделать две строки равными.
Пример:
👨💻 Алгоритм:
1⃣ Создайте двумерный массив dp размером (len(s1) + 1) x (len(s2) + 1), где dp[i][j] будет хранить наименьшую ASCII-сумму удаленных символов для первых i символов s1 и первых j символов s2.
2⃣ Заполните первую строку и первый столбец массива dp суммами ASCII значений символов, которые необходимо удалить для достижения пустой строки.
3⃣ Заполните оставшуюся часть массива dp следующим образом: Если символы s1[i-1] и s2[j-1] равны, dp[i][j] = dp[i-1][j-1]. Иначе, dp[i][j] = min(dp[i-1][j] + ord(s1[i-1]), dp[i][j-1] + ord(s2[j-1])).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 712. Minimum ASCII Delete Sum for Two Strings
Если даны две строки s1 и s2, верните наименьшую ASCII-сумму удаленных символов, чтобы сделать две строки равными.
Пример:
Input: s1 = "sea", s2 = "eat"
Output: 231
package main
func minimumDeleteSum(s1 string, s2 string) int {
dp := make([][]int, len(s1) + 1)
for i := range dp {
dp[i] = make([]int, len(s2) + 1)
}
for i := 1; i <= len(s1); i++ {
dp[i][0] = dp[i - 1][0] + int(s1[i - 1])
}
for j := 1; j <= len(s2); j++ {
dp[0][j] = dp[0][j - 1] + int(s2[j - 1])
}
for i := 1; i <= len(s1); i++ {
for j := 1; j <= len(s2); j++ {
if s1[i - 1] == s2[j - 1] {
dp[i][j] = dp[i - 1][j - 1]
} else {
dp[i][j] = min(dp[i - 1][j] + int(s1[i - 1]), dp[i][j - 1] + int(s2[j - 1]))
}
}
}
return dp[len(s1)][len(s2)]
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 767. Reorganize String
Дана строка s, переставьте символы строки s так, чтобы любые два соседних символа не были одинаковыми.
Верните любую возможную перестановку строки s или верните "", если это невозможно.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте пустой список ans для хранения переставленных символов. Создайте приоритетную очередь pq, используя структуру данных кучи. Каждый элемент в pq — это кортеж, содержащий количество символов и сам символ. Приоритетная очередь упорядочена так, что элементы с большим количеством имеют более высокий приоритет.
2⃣ Извлеките элемент с наивысшим приоритетом из pq. Присвойте его количество и символ переменным count_first и char_first соответственно. Если ans пуст или текущий символ char_first отличается от последнего символа в ans, добавьте char_first в ans. Если количество char_first не равно нулю, уменьшите его на один. Если обновленное количество больше нуля, поместите его обратно в pq. Перейдите к следующей итерации.
3⃣ В противном случае, если char_first совпадает с последним символом в ans, нужно выбрать другой символ. Если pq пуста, верните пустую строку, так как переставить символы невозможно. Извлеките следующий элемент из pq, присвоив его количество и символ переменным count_second и char_second соответственно. Добавьте char_second в ans. Если количество char_second не равно нулю, уменьшите его на один. Если обновленное количество больше нуля, поместите его обратно в pq. Наконец, поместите оригинальный char_first обратно в pq. Верните переставленные символы как строку, объединив элементы в ans.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 767. Reorganize String
Дана строка s, переставьте символы строки s так, чтобы любые два соседних символа не были одинаковыми.
Верните любую возможную перестановку строки s или верните "", если это невозможно.
Пример:
Input: s = "aab"
Output: "aba"
import (
"container/heap"
)
type Element struct {
count int
char byte
}
type PriorityQueue []*Element
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool { return pq[i].count > pq[j].count }
func (pq PriorityQueue) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] }
func (pq *PriorityQueue) Push(x interface{}) { *pq = append(*pq, x.(*Element)) }
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
x := old[n-1]
*pq = old[0 : n-1]
return x
}
func reorganizeString(s string) string {
charCounts := make([]int, 26)
for _, c := range s {
charCounts[c-'a']++
}
pq := &PriorityQueue{}
heap.Init(pq)
for i := 0; i < 26; i++ {
if charCounts[i] > 0 {
heap.Push(pq, &Element{charCounts[i], byte(i + 'a')})
}
}
result := []byte{}
for pq.Len() > 0 {
first := heap.Pop(pq).(*Element)
if len(result) == 0 || first.char != result[len(result)-1] {
result = append(result, first.char)
if first.count > 1 {
first.count--
heap.Push(pq, first)
}
} else {
if pq.Len() == 0 {
return ""
}
second := heap.Pop(pq).(*Element)
result = append(result, second.char)
if second.count > 1 {
second.count--
heap.Push(pq, second)
}
heap.Push(pq, first)
}
}
return string(result)
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 713. Subarray Product Less Than K
Если задан массив целых чисел nums и целое число k, верните количество смежных подмассивов, в которых произведение всех элементов в подмассиве строго меньше k.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте переменные для отслеживания текущего произведения и количества допустимых подмассивов. Используйте два указателя для границ подмассива.
2⃣ Перемещайте правый указатель по массиву и умножайте текущий элемент на текущее произведение. Если произведение становится больше или равно k, перемещайте левый указатель, уменьшая произведение до тех пор, пока оно снова не станет меньше k.
3⃣ Подсчитайте количество подмассивов с текущим правым указателем, добавив к общему количеству допустимых подмассивов разницу между правым и левым указателями.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 713. Subarray Product Less Than K
Если задан массив целых чисел nums и целое число k, верните количество смежных подмассивов, в которых произведение всех элементов в подмассиве строго меньше k.
Пример:
Input: nums = [10,5,2,6], k = 100
Output: 8
package main
func numSubarrayProductLessThanK(nums []int, k int) int {
if k <= 1 {
return 0
}
product, count, left := 1, 0, 0
for right := 0; right < len(nums); right++ {
product *= nums[right]
for product >= k {
product /= nums[left]
left++
}
count += right - left + 1
}
return count
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
#medium
Задача: 771. Jewels and Stones
Вам даны строки jewels, представляющие типы камней, которые являются драгоценностями, и stones, представляющие камни, которые у вас есть. Каждый символ в stones является типом камня, который у вас есть. Вы хотите узнать, сколько из камней, которые у вас есть, также являются драгоценностями.
Буквы чувствительны к регистру, поэтому "a" считается другим типом камня, чем "A".
Пример:
👨💻 Алгоритм:
1⃣ Создайте множество из строки jewels для быстрой проверки, является ли камень драгоценностью. Это позволит эффективно проверять принадлежность каждого камня к драгоценностям.
2⃣ Инициализируйте счетчик для подсчета количества камней, которые являются драгоценностями. Пройдите по каждому символу в строке stones и проверьте, содержится ли этот символ в множестве jewels.
3⃣ Если символ содержится в множестве, увеличьте счетчик. В конце верните значение счетчика, которое будет количеством камней, являющихся драгоценностями.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 771. Jewels and Stones
Вам даны строки jewels, представляющие типы камней, которые являются драгоценностями, и stones, представляющие камни, которые у вас есть. Каждый символ в stones является типом камня, который у вас есть. Вы хотите узнать, сколько из камней, которые у вас есть, также являются драгоценностями.
Буквы чувствительны к регистру, поэтому "a" считается другим типом камня, чем "A".
Пример:
Input: jewels = "aA", stones = "aAAbbbb"
Output: 3
func numJewelsInStones(J string, S string) int {
ans := 0
for _, s := range S {
for _, j := range J {
if j == s {
ans++
break
}
}
}
return ans
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 487. Max Consecutive Ones II
Дан бинарный массив nums, верните максимальное количество последовательных единиц в массиве, если можно перевернуть не более одного нуля.
Пример:
👨💻 Алгоритм:
1⃣ Для каждого возможного начала последовательности в массиве nums начните считать количество нулей.
2⃣ Для каждой последовательности проверяйте, сколько нулей содержится в ней. Если количество нулей не превышает одного, обновите максимальную длину последовательности единиц.
3⃣ Продолжайте проверять все возможные последовательности в массиве, и верните максимальную длину последовательности единиц, удовлетворяющую условию.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 487. Max Consecutive Ones II
Дан бинарный массив nums, верните максимальное количество последовательных единиц в массиве, если можно перевернуть не более одного нуля.
Пример:
Input: nums = [1,0,1,1,0]
Output: 4
Explanation:
- If we flip the first zero, nums becomes [1,1,1,1,0] and we have 4 consecutive ones.
- If we flip the second zero, nums becomes [1,0,1,1,1] and we have 3 consecutive ones.
The max number of consecutive ones is 4.
func findMaxConsecutiveOnes(nums []int) int {
longestSequence := 0
for left := 0; left < len(nums); left++ {
numZeroes := 0
for right := left; right < len(nums); right++ {
if nums[right] == 0 {
numZeroes++
}
if numZeroes <= 1 {
longestSequence = max(longestSequence, right - left + 1)
}
}
}
return longestSequence
}
func max(a, b int) int {
if a > b {
return a
}
return b
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 714. Best Time to Buy and Sell Stock with Transaction Fee
Вам дан массив prices, где prices[i] - это цена данной акции в i-й день, и целое число fee, представляющее собой комиссию за сделку. Найдите максимальную прибыль, которую вы можете получить. Вы можете совершить сколько угодно сделок, но за каждую сделку вам придется заплатить комиссию. Примечание: Вы не можете совершать несколько сделок одновременно (то есть вы должны продать акции, прежде чем купить их снова). Комиссия за сделку взимается только один раз за каждую покупку и продажу акций.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте две переменные: cash, представляющую максимальную прибыль без наличия акций, и hold, представляющую максимальную прибыль с наличием акций.
2⃣ Пройдите по каждому элементу массива prices и обновите значения cash и hold, используя текущую цену и комиссию.
3⃣ Верните значение cash, которое будет максимальной прибылью без наличия акций.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 714. Best Time to Buy and Sell Stock with Transaction Fee
Вам дан массив prices, где prices[i] - это цена данной акции в i-й день, и целое число fee, представляющее собой комиссию за сделку. Найдите максимальную прибыль, которую вы можете получить. Вы можете совершить сколько угодно сделок, но за каждую сделку вам придется заплатить комиссию. Примечание: Вы не можете совершать несколько сделок одновременно (то есть вы должны продать акции, прежде чем купить их снова). Комиссия за сделку взимается только один раз за каждую покупку и продажу акций.
Пример:
Input: prices = [1,3,2,8,4,9], fee = 2
Output: 8
package main
func maxProfit(prices []int, fee int) int {
cash, hold := 0, -prices[0]
for _, price := range prices {
cash = max(cash, hold + price - fee)
hold = max(hold, cash - price)
}
return cash
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
#medium
Задача: 772. Basic Calculator III
Реализуйте базовый калькулятор для вычисления простого строкового выражения.
Строка выражения содержит только неотрицательные целые числа, операторы '+', '-', '*', '/' и открывающие '(' и закрывающие скобки ')'. Целочисленное деление должно округляться к нулю.
Предполагается, что данное выражение всегда корректно. Все промежуточные результаты будут находиться в диапазоне [-2^31, 2^31 - 1].
Примечание: нельзя использовать встроенные функции для вычисления строк как математических выражений, такие как eval().
Пример:
👨💻 Алгоритм:
1⃣ Определите вспомогательную функцию evaluate, которая принимает оператор и числовые аргументы. Заметьте, что эта функция идентична той, что представлена в подходе "Basic Calculator II". Инициализируйте несколько переменных: стек для хранения промежуточных результатов, curr для отслеживания текущего числа, которое мы строим, и previousOperator для отслеживания предыдущего оператора. Добавьте в строку s случайный символ, который не будет появляться во входных данных, например "@".
2⃣ Итерация по входным данным. Для каждого символа c: если c является цифрой, добавьте его к curr. В противном случае, если c == '(', мы начинаем вычисление нового изолированного выражения. В этом случае сохраните previousOperator в стек и установите previousOperator = "+".
3⃣ Если c является оператором, то необходимо вычислить значение curr. Используйте функцию evaluate, чтобы применить previousOperator к curr, и добавьте результат в стек. Затем сбросьте curr до нуля и обновите previousOperator = c. Если c == ')', это означает, что мы находимся в конце изолированного выражения и должны полностью его вычислить. Извлекайте из стека до тех пор, пока не достигнете оператора, суммируя все извлеченные числа в curr. Как только достигнете оператора, обновите previousOperator = stack.pop(). Верните сумму всех чисел в стеке.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 772. Basic Calculator III
Реализуйте базовый калькулятор для вычисления простого строкового выражения.
Строка выражения содержит только неотрицательные целые числа, операторы '+', '-', '*', '/' и открывающие '(' и закрывающие скобки ')'. Целочисленное деление должно округляться к нулю.
Предполагается, что данное выражение всегда корректно. Все промежуточные результаты будут находиться в диапазоне [-2^31, 2^31 - 1].
Примечание: нельзя использовать встроенные функции для вычисления строк как математических выражений, такие как eval().
Пример:
Input: s = "1+1"
Output: 2
package main
import (
"strconv"
)
type Solution struct{}
func (sol *Solution) evaluate(operator byte, first, second string) string {
x, _ := strconv.Atoi(first)
y, _ := strconv.Atoi(second)
res := 0
if operator == '+' {
res = x
} else if operator == '-' {
res = -x
} else if operator == '*' {
res = x * y
} else {
res = x / y
}
return strconv.Itoa(res)
}
func (sol *Solution) calculate(s string) int {
stack := []string{}
curr := ""
previousOperator := byte('+')
s += "@"
operators := map[string]struct{}{"+": {}, "-": {}, "*": {}, "/": {}}
for i := 0; i < len(s); i++ {
c := s[i]
if c >= '0' && c <= '9' {
curr += string(c)
} else if c == '(' {
stack = append(stack, string(previousOperator))
previousOperator = '+'
} else {
if previousOperator == '*' || previousOperator == '/' {
top := stack[len(stack)-1]
stack = stack[:len(stack)-1]
stack = append(stack, sol.evaluate(previousOperator, top, curr))
} else {
stack = append(stack, sol.evaluate(previousOperator, curr, "0"))
}
curr = ""
previousOperator = c
if c == ')' {
currentTerm := 0
for len(stack) > 0 {
top := stack[len(stack)-1]
if _, ok := operators[top]; ok {
break
}
stack = stack[:len(stack)-1]
val, _ := strconv.Atoi(top)
currentTerm += val
}
curr = strconv.Itoa(currentTerm)
previousOperator = stack[len(stack)-1][0]
stack = stack[:len(stack)-1]
}
}
}
ans := 0
for _, num := range stack {
val, _ := strconv.Atoi(num)
ans += val
}
return ans
}
func main() {}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 774. Minimize Max Distance to Gas Station
Вам дан массив целых чисел stations, который представляет позиции автозаправочных станций на оси x. Вам также дано целое число k.
Вы должны добавить k новых автозаправочных станций. Вы можете добавлять станции в любое место на оси x, необязательно в целочисленную позицию.
Определим penalty() как максимальное расстояние между соседними автозаправочными станциями после добавления k новых станций.
Верните наименьшее возможное значение penalty(). Ответы, отличающиеся от фактического ответа не более чем на 10^-6, будут приняты.
Пример:
👨💻 Алгоритм:
1⃣ Пусть i-й интервал равен deltas[i] = stations[i+1] - stations[i]. Мы хотим найти dp[n+1][k] как рекурсию. Мы можем поставить x автозаправочных станций в интервал n+1 с наилучшим расстоянием deltas[n+1] / (x+1), затем оставшиеся интервалы можно решить с ответом dp[n][k-x]. Ответ — это минимум среди всех x.
2⃣ Из этой рекурсии мы можем разработать решение с использованием динамического программирования. Инициализируем двумерный массив dp, где dp[i][j] будет хранить минимальное возможное значение penalty при добавлении j автозаправочных станций на первые i интервалов.
3⃣ Заполняем dp таблицу начиная с базового случая, когда нет добавленных станций. Затем для каждого интервала и количества добавленных станций вычисляем минимальное значение penalty, используя вышеописанную рекурсию. Итоговый ответ будет находиться в dp[n][k], где n — количество интервалов, а k — количество добавляемых станций.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 774. Minimize Max Distance to Gas Station
Вам дан массив целых чисел stations, который представляет позиции автозаправочных станций на оси x. Вам также дано целое число k.
Вы должны добавить k новых автозаправочных станций. Вы можете добавлять станции в любое место на оси x, необязательно в целочисленную позицию.
Определим penalty() как максимальное расстояние между соседними автозаправочными станциями после добавления k новых станций.
Верните наименьшее возможное значение penalty(). Ответы, отличающиеся от фактического ответа не более чем на 10^-6, будут приняты.
Пример:
Input: stations = [1,2,3,4,5,6,7,8,9,10], k = 9
Output: 0.50000
func minmaxGasDist(stations []int, K int) float64 {
N := len(stations)
deltas := make([]float64, N-1)
for i := 0; i < N-1; i++ {
deltas[i] = float64(stations[i+1] - stations[i])
}
dp := make([][]float64, N-1)
for i := range dp {
dp[i] = make([]float64, K+1)
}
for i := 0; i <= K; i++ {
dp[0][i] = deltas[0] / float64(i+1)
}
for p := 1; p < N-1; p++ {
for k := 0; k <= K; k++ {
bns := 1e9
for x := 0; x <= k; x++ {
bns = math.Min(bns, math.Max(deltas[p] / float64(x+1), dp[p-1][k-x]))
}
dp[p][k] = bns
}
}
return dp[N-2][K]
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM