#medium
Задача: 208. Implement Trie (Prefix Tree)
Trie (произносится как "трай") или префиксное дерево — это древовидная структура данных, используемая для эффективного хранения и поиска ключей в наборе строк. Существует множество применений этой структуры данных, таких как автозаполнение и проверка орфографии.
Реализуйте класс Trie:
Trie() инициализирует объект trie.
void insert(String word) вставляет строку word в trie.
boolean search(String word) возвращает true, если строка word есть в trie (то есть была вставлена ранее), и false в противном случае.
boolean startsWith(String prefix) возвращает true, если есть ранее вставленная строка word, которая имеет префикс prefix, и false в противном случае.
Пример:
👨💻 Алгоритм:
1️⃣ Инициализация и вставка в Trie:
Создайте класс Trie, который включает в себя метод insert(String word) для добавления строк в Trie.
Метод insert инициализирует текущий узел как корень и проходит по каждому символу строки. Если текущий узел не содержит символа, создайте новый узел. В конце отметьте последний узел как конец слова.
2️⃣ Поиск строки в Trie:
Создайте метод search(String word), который использует вспомогательный метод searchPrefix(String word) для поиска строки или префикса в Trie.
В методе searchPrefix начните с корневого узла и для каждого символа строки перемещайтесь к следующему узлу. Если на каком-то этапе узел не содержит текущего символа, верните null. В противном случае, в конце строки верните текущий узел.
3️⃣ Проверка наличия префикса в Trie:
Создайте метод startsWith(String prefix), который также использует метод searchPrefix(String prefix).
Метод startsWith вызывает searchPrefix и возвращает true, если возвращаемый узел не равен null, что указывает на наличие префикса в Trie.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 208. Implement Trie (Prefix Tree)
Trie (произносится как "трай") или префиксное дерево — это древовидная структура данных, используемая для эффективного хранения и поиска ключей в наборе строк. Существует множество применений этой структуры данных, таких как автозаполнение и проверка орфографии.
Реализуйте класс Trie:
Trie() инициализирует объект trie.
void insert(String word) вставляет строку word в trie.
boolean search(String word) возвращает true, если строка word есть в trie (то есть была вставлена ранее), и false в противном случае.
boolean startsWith(String prefix) возвращает true, если есть ранее вставленная строка word, которая имеет префикс prefix, и false в противном случае.
Пример:
Input
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
Output
[null, null, true, false, true, null, true]
Explanation
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // return True
trie.search("app"); // return False
trie.startsWith("app"); // return True
trie.insert("app");
trie.search("app"); // return True
Создайте класс Trie, который включает в себя метод insert(String word) для добавления строк в Trie.
Метод insert инициализирует текущий узел как корень и проходит по каждому символу строки. Если текущий узел не содержит символа, создайте новый узел. В конце отметьте последний узел как конец слова.
Создайте метод search(String word), который использует вспомогательный метод searchPrefix(String word) для поиска строки или префикса в Trie.
В методе searchPrefix начните с корневого узла и для каждого символа строки перемещайтесь к следующему узлу. Если на каком-то этапе узел не содержит текущего символа, верните null. В противном случае, в конце строки верните текущий узел.
Создайте метод startsWith(String prefix), который также использует метод searchPrefix(String prefix).
Метод startsWith вызывает searchPrefix и возвращает true, если возвращаемый узел не равен null, что указывает на наличие префикса в Trie.
public class TrieNode {
private TrieNode[] links = new TrieNode[26];
private bool isEnd;
public bool ContainsKey(char ch) {
return links[ch - 'a'] != null;
}
public TrieNode Get(char ch) {
return links[ch - 'a'];
}
public void Put(char ch, TrieNode node) {
links[ch - 'a'] = node;
}
public void SetEnd() {
isEnd = true;
}
public bool IsEnd() {
return isEnd;
}
}
public class Trie {
private TrieNode root = new TrieNode();
public void Insert(string word) {
TrieNode node = root;
foreach (char ch in word) {
if (!node.ContainsKey(ch)) {
node.Put(ch, new TrieNode());
}
node = node.Get(ch);
}
node.SetEnd();
}
private TrieNode SearchPrefix(string word) {
TrieNode node = root;
foreach (char ch in word) {
if (node.ContainsKey(ch)) {
node = node.Get(ch);
} else {
return null;
}
}
return node;
}
public bool Search(string word) {
TrieNode node = SearchPrefix(word);
return node != null && node.IsEnd();
}
public bool StartsWith(string prefix) {
return SearchPrefix(prefix) != null;
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 210. Course Schedule II
Всего есть numCourses курсов, которые вы должны пройти, пронумерованных от 0 до numCourses - 1. Вам дан массив prerequisites, где prerequisites[i] = [ai, bi] указывает на то, что вы должны сначала пройти курс bi, если хотите взять курс ai.
Например, пара [0, 1] указывает на то, что для прохождения курса 0 сначала нужно пройти курс 1.
Верните порядок курсов, которые вы должны пройти, чтобы завершить все курсы. Если существует несколько правильных ответов, верните любой из них. Если невозможно завершить все курсы, верните пустой массив.
Пример:
👨💻 Алгоритм:
1️⃣ Инициализация и построение графа:
Инициализируйте стек S, который будет содержать топологически отсортированный порядок курсов в нашем графе.
Постройте список смежности, используя пары ребер, указанные на входе. Важно отметить, что пара вида [a, b] указывает на то, что курс b должен быть пройден, чтобы взять курс a. Это подразумевает ребро вида b ➔ a. Учтите это при реализации алгоритма.
2️⃣ Запуск поиска в глубину (DFS):
Для каждого узла в нашем графе выполните поиск в глубину (DFS), если этот узел еще не был посещен во время DFS другого узла.
Предположим, что мы выполняем поиск в глубину для узла N. Рекурсивно обойдите всех соседей узла N, которые еще не были обработаны.
3️⃣ Обработка узлов и возвращение результата:
После обработки всех соседей добавьте узел N в стек. Мы используем стек для моделирования необходимого порядка. Когда мы добавляем узел N в стек, все узлы, которые требуют узел N в качестве предшественника (среди других), уже будут в стеке.
После обработки всех узлов просто верните узлы в порядке их присутствия в стеке от вершины до основания.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 210. Course Schedule II
Всего есть numCourses курсов, которые вы должны пройти, пронумерованных от 0 до numCourses - 1. Вам дан массив prerequisites, где prerequisites[i] = [ai, bi] указывает на то, что вы должны сначала пройти курс bi, если хотите взять курс ai.
Например, пара [0, 1] указывает на то, что для прохождения курса 0 сначала нужно пройти курс 1.
Верните порядок курсов, которые вы должны пройти, чтобы завершить все курсы. Если существует несколько правильных ответов, верните любой из них. Если невозможно завершить все курсы, верните пустой массив.
Пример:
Input: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
Output: [0,2,1,3]
Объяснение: Всего есть 4 курса, которые нужно пройти. Чтобы взять курс 3, вы должны завершить оба курса 1 и 2. Оба курса 1 и 2 должны быть взяты после того, как вы завершите курс 0.
Таким образом, один из правильных порядков курсов — [0,1,2,3]. Другой правильный порядок — [0,2,1,3].
Инициализируйте стек S, который будет содержать топологически отсортированный порядок курсов в нашем графе.
Постройте список смежности, используя пары ребер, указанные на входе. Важно отметить, что пара вида [a, b] указывает на то, что курс b должен быть пройден, чтобы взять курс a. Это подразумевает ребро вида b ➔ a. Учтите это при реализации алгоритма.
Для каждого узла в нашем графе выполните поиск в глубину (DFS), если этот узел еще не был посещен во время DFS другого узла.
Предположим, что мы выполняем поиск в глубину для узла N. Рекурсивно обойдите всех соседей узла N, которые еще не были обработаны.
После обработки всех соседей добавьте узел N в стек. Мы используем стек для моделирования необходимого порядка. Когда мы добавляем узел N в стек, все узлы, которые требуют узел N в качестве предшественника (среди других), уже будут в стеке.
После обработки всех узлов просто верните узлы в порядке их присутствия в стеке от вершины до основания.
public class Solution {
private const int WHITE = 1;
private const int GRAY = 2;
private const int BLACK = 3;
public int[] FindOrder(int numCourses, int[][] prerequisites) {
bool isPossible = true;
var color = new Dictionary<int, int>();
var adjList = new Dictionary<int, List<int>>();
var topologicalOrder = new List<int>();
for (int i = 0; i < numCourses; i++) color[i] = WHITE;
foreach (var relation in prerequisites) {
int dest = relation[0];
int src = relation[1];
if (!adjList.ContainsKey(src)) adjList[src] = new List<int>();
adjList[src].Add(dest);
}
for (int i = 0; i < numCourses && isPossible; i++) {
if (color[i] == WHITE) {
Dfs(i, color, adjList, ref isPossible, topologicalOrder);
}
}
if (isPossible) {
var order = new int[numCourses];
for (int i = 0; i < numCourses; i++) {
order[i] = topologicalOrder[numCourses - i - 1];
}
return order;
} else {
return new int[0];
}
}
private void Dfs(int node, Dictionary<int, int> color, Dictionary<int, List<int>> adjList,
ref bool isPossible, List<int> topologicalOrder) {
if (!isPossible) return;
color[node] = GRAY;
if (adjList.ContainsKey(node)) {
foreach (int neighbor in adjList[node]) {
if (color[neighbor] == WHITE) {
Dfs(neighbor, color, adjList, ref isPossible, topologicalOrder);
} else if (color[neighbor] == GRAY) {
isPossible = false;
}
}
}
color[node] = BLACK;
topologicalOrder.Add(node);
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
#easy
Задача: 252. Meeting Rooms
Дан массив интервалов времени встреч, где intervals[i] = [starti, endi]. Определите, может ли человек посетить все встречи.
Пример:
👨💻 Алгоритм:
1️⃣ Создайте функцию для проверки перекрытия двух интервалов:
Возвращайте true, если начало одного интервала находится внутри другого интервала.
2️⃣ Проверьте каждый интервал с каждым другим интервалом:
Если найдено перекрытие, верните false.
3️⃣ Если все интервалы проверены и перекрытий не найдено, верните true.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 252. Meeting Rooms
Дан массив интервалов времени встреч, где intervals[i] = [starti, endi]. Определите, может ли человек посетить все встречи.
Пример:
Input: intervals = [[0,30],[5,10],[15,20]]
Output: false
Возвращайте true, если начало одного интервала находится внутри другого интервала.
Если найдено перекрытие, верните false.
class Solution {
public bool Overlap(int[] interval1, int[] interval2) {
return (interval1[0] >= interval2[0] && interval1[0] < interval2[1]) ||
(interval2[0] >= interval1[0] && interval2[0] < interval1[1]);
}
public bool CanAttendMeetings(int[][] intervals) {
for (int i = 0; i < intervals.Length; i++) {
for (int j = i + 1; j < intervals.Length; j++) {
if (Overlap(intervals[i], intervals[j])) {
return false;
}
}
}
return true;
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 253. Meeting Rooms II
Дан массив интервалов времени встреч intervals, где intervals[i] = [starti, endi]. Верните минимальное количество необходимых конференц-залов.
Пример:
👨💻 Алгоритм:
1️⃣ Отсортируйте встречи по времени их начала и инициализируйте мин-кучу с временем окончания первой встречи.
2️⃣ Для каждой последующей встречи проверьте, свободна ли комната (сравните время начала встречи с минимальным временем окончания в куче):
Если свободна, обновите время окончания этой комнаты.
Если не свободна, добавьте новое время окончания в кучу.
3️⃣ После обработки всех встреч размер кучи будет равен минимальному количеству необходимых комнат.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 253. Meeting Rooms II
Дан массив интервалов времени встреч intervals, где intervals[i] = [starti, endi]. Верните минимальное количество необходимых конференц-залов.
Пример:
Input: intervals = [[0,30],[5,10],[15,20]]
Output: 2
Если свободна, обновите время окончания этой комнаты.
Если не свободна, добавьте новое время окончания в кучу.
using System;
using System.Collections.Generic;
public class Solution {
public int MinMeetingRooms(int[][] intervals) {
Array.Sort(intervals, (a, b) => a[0] - b[0]);
var heap = new SortedSet<int>();
heap.Add(intervals[0][1]);
for (int i = 1; i < intervals.Length; i++) {
if (intervals[i][0] >= heap.Min) {
heap.Remove(heap.Min);
}
heap.Add(intervals[i][1]);
}
return heap.Count;
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 254. Factor Combinations
Числа можно рассматривать как произведение их множителей.
Например, 8 = 2 x 2 x 2 = 2 x 4.
Дано целое число n, верните все возможные комбинации его множителей. Вы можете вернуть ответ в любом порядке.
Обратите внимание, что множители должны быть в диапазоне [2, n - 1].
Пример:
👨💻 Алгоритм:
1️⃣ Определите вспомогательную функцию backtracking, которая принимает два параметра: factors (список множителей) и ans (список списков для сохранения всех комбинаций множителей). Начните вызов backtracking с factors, содержащим только n, и пустым списком ans.
2️⃣ Основная логика функции backtracking:
Если размер factors больше 1, добавьте его копию в ans, так как это одно из желаемых решений.
Получите последний элемент factors (lastFactor) и удалите его из factors.
Если factors пуст, итерируйте i от 2. В противном случае, итерируйте i от последнего значения в factors. Итерируйте, пока i <= lastFactor / i.
Для каждого i, если lastFactor % i == 0, добавьте i и lastFactor / i в factors и вызовите backtracking(factors, ans).
Восстановите список (откат) factors, удалив последние два элемента из factors.
Восстановите список (откат) factors, добавив обратно lastFactor.
3️⃣ В конце выполнения, ans будет содержать все возможные комбинации множителей числа n.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 254. Factor Combinations
Числа можно рассматривать как произведение их множителей.
Например, 8 = 2 x 2 x 2 = 2 x 4.
Дано целое число n, верните все возможные комбинации его множителей. Вы можете вернуть ответ в любом порядке.
Обратите внимание, что множители должны быть в диапазоне [2, n - 1].
Пример:
Input: n = 1
Output: []
Если размер factors больше 1, добавьте его копию в ans, так как это одно из желаемых решений.
Получите последний элемент factors (lastFactor) и удалите его из factors.
Если factors пуст, итерируйте i от 2. В противном случае, итерируйте i от последнего значения в factors. Итерируйте, пока i <= lastFactor / i.
Для каждого i, если lastFactor % i == 0, добавьте i и lastFactor / i в factors и вызовите backtracking(factors, ans).
Восстановите список (откат) factors, удалив последние два элемента из factors.
Восстановите список (откат) factors, добавив обратно lastFactor.
using System;
using System.Collections.Generic;
public class Solution {
private void Backtracking(LinkedList<int> factors, List<IList<int>> ans) {
if (factors.Count > 1) {
ans.Add(new List<int>(factors));
}
int lastFactor = factors.Last.Value;
factors.RemoveLast();
for (int i = factors.Count == 0 ? 2 : factors.Last.Value; i <= lastFactor / i; ++i) {
if (lastFactor % i == 0) {
factors.AddLast(i);
factors.AddLast(lastFactor / i);
Backtracking(factors, ans);
factors.RemoveLast();
factors.RemoveLast();
}
}
factors.AddLast(lastFactor);
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 255. Verify Preorder Sequence in Binary Search Tree
Дан массив уникальных целых чисел preorder. Верните true, если это правильная последовательность обхода в порядке предварительного (preorder) обхода для бинарного дерева поиска.
Пример:
👨💻 Алгоритм:
1️⃣ Объявите целое число minLimit с маленьким значением, например, минус бесконечность, и стек.
2️⃣ Итерируйте по массиву preorder. Для каждого num:
Очистите стек. Пока верх стека меньше num, извлекайте из стека и обновляйте minLimit.
Если num <= minLimit, верните false.
Добавьте num в стек.
3️⃣ Верните true, если удалось пройти весь массив.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 255. Verify Preorder Sequence in Binary Search Tree
Дан массив уникальных целых чисел preorder. Верните true, если это правильная последовательность обхода в порядке предварительного (preorder) обхода для бинарного дерева поиска.
Пример:
Input: preorder = [5,2,1,3,6]
Output: true
Очистите стек. Пока верх стека меньше num, извлекайте из стека и обновляйте minLimit.
Если num <= minLimit, верните false.
Добавьте num в стек.
using System;
using System.Collections.Generic;
public class Solution {
public bool VerifyPreorder(int[] preorder) {
int minLimit = int.MinValue;
Stack<int> stack = new Stack<int>();
foreach (int num in preorder) {
while (stack.Count > 0 && stack.Peek() < num) {
minLimit = stack.Pop();
}
if (num <= minLimit) {
return false;
}
stack.Push(num);
}
return true;
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 211. Design Add and Search Words Data Structure
Спроектируйте структуру данных, которая поддерживает добавление новых слов и проверку, соответствует ли строка любому ранее добавленному слову.
Реализуйте класс WordDictionary:
WordDictionary() инициализирует объект.
void addWord(word) добавляет слово в структуру данных, оно может быть сопоставлено позже.
bool search(word) возвращает true, если в структуре данных есть строка, которая соответствует слову, или false в противном случае. Слово может содержать точки '.', где точки могут быть сопоставлены с любой буквой.
Пример:
👨💻 Алгоритм:
1️⃣ Инициализация и добавление слова:
Создайте класс WordDictionary с конструктором, который инициализирует корневой узел TrieNode.
Метод addWord(String word) добавляет слово в структуру данных. Инициализируйте текущий узел как корневой и пройдите по каждому символу слова. Если символ отсутствует среди дочерних узлов текущего узла, создайте новый узел. Перемещайтесь к следующему узлу. В конце отметьте текущий узел как конец слова.
2️⃣ Поиск слова в узле:
Метод searchInNode(String word, TrieNode node) ищет слово в переданном узле TrieNode. Пройдите по каждому символу слова. Если символ не найден среди дочерних узлов текущего узла, проверьте, является ли символ точкой '.'. Если да, рекурсивно выполните поиск в каждом дочернем узле текущего узла. Если символ не точка и не найден, верните false. Если символ найден, перейдите к следующему узлу. В конце проверьте, является ли текущий узел концом слова.
3️⃣ Поиск слова в структуре данных:
Метод search(String word) использует метод searchInNode() для поиска слова, начиная с корневого узла. Верните результат поиска. Если слово найдено, верните true, иначе false.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 211. Design Add and Search Words Data Structure
Спроектируйте структуру данных, которая поддерживает добавление новых слов и проверку, соответствует ли строка любому ранее добавленному слову.
Реализуйте класс WordDictionary:
WordDictionary() инициализирует объект.
void addWord(word) добавляет слово в структуру данных, оно может быть сопоставлено позже.
bool search(word) возвращает true, если в структуре данных есть строка, которая соответствует слову, или false в противном случае. Слово может содержать точки '.', где точки могут быть сопоставлены с любой буквой.
Пример:
Input
["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
Output
[null,null,null,null,false,true,true,true]
Explanation
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord("bad");
wordDictionary.addWord("dad");
wordDictionary.addWord("mad");
wordDictionary.search("pad"); // return False
wordDictionary.search("bad"); // return True
wordDictionary.search(".ad"); // return True
wordDictionary.search("b.."); // return True
Создайте класс WordDictionary с конструктором, который инициализирует корневой узел TrieNode.
Метод addWord(String word) добавляет слово в структуру данных. Инициализируйте текущий узел как корневой и пройдите по каждому символу слова. Если символ отсутствует среди дочерних узлов текущего узла, создайте новый узел. Перемещайтесь к следующему узлу. В конце отметьте текущий узел как конец слова.
Метод searchInNode(String word, TrieNode node) ищет слово в переданном узле TrieNode. Пройдите по каждому символу слова. Если символ не найден среди дочерних узлов текущего узла, проверьте, является ли символ точкой '.'. Если да, рекурсивно выполните поиск в каждом дочернем узле текущего узла. Если символ не точка и не найден, верните false. Если символ найден, перейдите к следующему узлу. В конце проверьте, является ли текущий узел концом слова.
Метод search(String word) использует метод searchInNode() для поиска слова, начиная с корневого узла. Верните результат поиска. Если слово найдено, верните true, иначе false.
using System.Collections.Generic;
class TrieNode {
public Dictionary<char, TrieNode> Children = new Dictionary<char, TrieNode>();
public bool IsWord = false;
}
class WordDictionary {
private TrieNode trie;
public WordDictionary() {
trie = new TrieNode();
}
public void AddWord(string word) {
TrieNode node = trie;
foreach (char ch in word) {
if (!node.Children.ContainsKey(ch)) {
node.Children[ch] = new TrieNode();
}
node = node.Children[ch];
}
node.IsWord = true;
}
private bool SearchInNode(string word, TrieNode node) {
for (int i = 0; i < word.Length; i++) {
char ch = word[i];
if (!node.Children.ContainsKey(ch)) {
if (ch == '.') {
foreach (var child in node.Children.Values) {
if (SearchInNode(word.Substring(i + 1), child)) {
return true;
}
}
}
return false;
} else {
node = node.Children[ch];
}
}
return node.IsWord;
}
public bool Search(string word) {
return SearchInNode(word, trie);
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 212. Word Search II
Дана m на n доска символов и список строк words, верните все слова, находящиеся на доске.
Каждое слово должно быть составлено из букв последовательных смежных ячеек, где смежные ячейки находятся по горизонтали или вертикали рядом. Одна и та же ячейка с буквой не может использоваться более одного раза в слове.
Пример:
👨💻 Алгоритм:
1️⃣ Построение Trie:
Постройте структуру Trie из слов в словаре. Trie будет использоваться для процесса сопоставления позже.
2️⃣ Запуск обхода в глубину (Backtracking) с каждой ячейки:
Начните обход доски с каждой ячейки. Если существует слово в словаре, которое начинается с буквы в данной ячейке, начните рекурсивный вызов функции backtracking(cell).
3️⃣ Обход соседних ячеек:
В функции backtracking(cell) исследуйте соседние ячейки (i.e. neighborCell) вокруг текущей ячейки для следующего рекурсивного вызова backtracking(neighborCell).
На каждом вызове проверяйте, соответствует ли последовательность букв, которую мы прошли до сих пор, какому-либо слову в словаре, используя структуру Trie, построенную в начале.
😎
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 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"]
Постройте структуру Trie из слов в словаре. Trie будет использоваться для процесса сопоставления позже.
Начните обход доски с каждой ячейки. Если существует слово в словаре, которое начинается с буквы в данной ячейке, начните рекурсивный вызов функции backtracking(cell).
В функции backtracking(cell) исследуйте соседние ячейки (i.e. neighborCell) вокруг текущей ячейки для следующего рекурсивного вызова backtracking(neighborCell).
На каждом вызове проверяйте, соответствует ли последовательность букв, которую мы прошли до сих пор, какому-либо слову в словаре, используя структуру Trie, построенную в начале.
using System;
using System.Collections.Generic;
class TrieNode {
public Dictionary<char, TrieNode> Children = new Dictionary<char, TrieNode>();
public string Word = null;
}
class Solution {
private char[][] board;
private List<string> result = new List<string>();
public IList<string> FindWords(char[][] board, string[] words) {
TrieNode root = BuildTrie(words);
this.board = board;
for (int row = 0; row < board.Length; ++row) {
for (int col = 0; col < board[row].Length; ++col) {
if (root.Children.ContainsKey(board[row][col])) {
Backtrack(row, col, root);
}
}
}
return result;
}
private TrieNode BuildTrie(string[] words) {
TrieNode root = new TrieNode();
foreach (string word in words) {
TrieNode node = root;
foreach (char letter in word) {
if (!node.Children.ContainsKey(letter)) {
node.Children[letter] = new TrieNode();
}
node = node.Children[letter];
}
node.Word = word;
}
return root;
}
private void Backtrack(int row, int col, TrieNode parent) {
char letter = board[row][col];
TrieNode currNode = parent.Children[letter];
if (currNode.Word != null) {
result.Add(currNode.Word);
currNode.Word = null;
}
board[row][col] = '#';
int[] rowOffset = { -1, 0, 1, 0 };
int[] colOffset = { 0, 1, 0, -1 };
for (int i = 0; i < 4; ++i) {
int newRow = row + rowOffset[i];
int newCol = col + colOffset[i];
if (newRow >= 0 && newRow < board.Length && newCol >= 0 && newCol < board[0].Length) {
if (currNode.Children.ContainsKey(board[newRow][newCol])) {
Backtrack(newRow, newCol, currNode);
}
}
}
board[row][col] = letter;
if (currNode.Children.Count == 0) {
parent.Children.Remove(letter);
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 256. Paint House
Есть ряд из n домов, где каждый дом можно покрасить в один из трёх цветов: красный, синий или зелёный. Стоимость покраски каждого дома в определённый цвет разная. Необходимо покрасить все дома так, чтобы никакие два соседних дома не были окрашены в один и тот же цвет.
Стоимость покраски каждого дома в определённый цвет представлена в виде матрицы стоимости n x 3.
Например, costs[0][0] — это стоимость покраски дома 0 в красный цвет; costs[1][2] — это стоимость покраски дома 1 в зелёный цвет и так далее...
Верните минимальную стоимость покраски всех домов.
Пример:
👨💻 Алгоритм:
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]).
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 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.
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])
public class Solution {
public int MinCost(int[][] costs) {
int n = costs.Length;
int[,] dp = new int[n, 3];
for (int j = 0; j < 3; j++) dp[0, j] = costs[0][j];
for (int i = 1; i < n; i++) {
dp[i, 0] = costs[i][0] + Math.Min(dp[i-1, 1], dp[i-1, 2]);
dp[i, 1] = costs[i][1] + Math.Min(dp[i-1, 0], dp[i-1, 2]);
dp[i, 2] = costs[i][2] + Math.Min(dp[i-1, 0], dp[i-1, 1]);
}
return Math.Min(dp[n-1, 0], Math.Min(dp[n-1, 1], dp[n-1, 2]));
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
#easy
Задача: 257. Binary Tree Paths
Дано корневое дерево, верните все пути от корня до листа в любом порядке.
Лист — это узел без детей.
Пример:
👨💻 Алгоритм:
1️⃣ Если текущий узел не является null, добавьте его значение к текущему пути.
Если текущий узел является листом (не имеет дочерних узлов), добавьте текущий путь в список путей.
Если текущий узел не является листом, добавьте "->" к текущему пути и рекурсивно вызовите функцию для левого и правого дочерних узлов.
2️⃣ Начните с корневого узла, пустого пути и пустого списка путей.
3️⃣ Верните список всех путей от корня до листа.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 257. Binary Tree Paths
Дано корневое дерево, верните все пути от корня до листа в любом порядке.
Лист — это узел без детей.
Пример:
Input: root = [1,2,3,null,5]
Output: ["1->2->5","1->3"]
Если текущий узел является листом (не имеет дочерних узлов), добавьте текущий путь в список путей.
Если текущий узел не является листом, добавьте "->" к текущему пути и рекурсивно вызовите функцию для левого и правого дочерних узлов.
public class Solution {
public void ConstructPaths(TreeNode root, string path, IList<string> paths) {
if (root != null) {
path += root.val;
if (root.left == null && root.right == null) {
paths.Add(path);
} else {
path += "->";
ConstructPaths(root.left, path, paths);
ConstructPaths(root.right, path, paths);
}
}
}
public IList<string> BinaryTreePaths(TreeNode root) {
IList<string> paths = new List<string>();
ConstructPaths(root, "", paths);
return paths;
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
#easy
Задача: 258. Add Digits
Дано целое число num. Повторно складывайте все его цифры, пока результат не станет однозначным, и верните его.
Пример:
👨💻 Алгоритм:
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.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 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.
Добавьте к digital_root последнюю цифру num.
Уменьшите num, удалив последнюю цифру.
Если num равно 0 и digital_root больше 9, присвойте num значение digital_root и сбросьте digital_root в 0.
public class Solution {
public int AddDigits(int num) {
int digital_root = 0;
while (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.
Пример:
👨💻 Алгоритм:
1️⃣ Отсортируйте массив nums.
2️⃣ Для каждого элемента nums[i] от 0 до n-3 найдите количество пар индексов j и k (где i < j < k), таких что nums[i] + nums[j] + nums[k] < target. Используйте функцию twoSumSmaller, которая ищет количество пар с суммой меньше заданного значения.
3️⃣ В функции twoSumSmaller используйте бинарный поиск для поиска верхней границы индекса k и подсчета количества подходящих пар.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 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]
using System;
public class Solution {
public int ThreeSumSmaller(int[] nums, int target) {
Array.Sort(nums);
int sum = 0;
for (int i = 0; i < nums.Length - 2; i++) {
sum += TwoSumSmaller(nums, i + 1, target - nums[i]);
}
return sum;
}
private int TwoSumSmaller(int[] nums, int startIndex, int target) {
int sum = 0;
for (int i = startIndex; i < nums.Length - 1; i++) {
int j = BinarySearch(nums, i, target - nums[i]);
sum += j - i;
}
return sum;
}
private int BinarySearch(int[] nums, int startIndex, int target) {
int left = startIndex;
int right = nums.Length - 1;
while (left < right) {
int 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, в котором ровно два элемента встречаются только один раз, а все остальные элементы встречаются ровно дважды. Найдите два элемента, которые встречаются только один раз. Вы можете вернуть ответ в любом порядке.
Вы должны написать алгоритм, который работает за линейное время и использует только постоянное дополнительное пространство..
Пример:
👨💻 Алгоритм:
1️⃣ Выполните XOR для всех элементов массива nums. Это даст результат, который является XOR двух уникальных чисел.
2️⃣ Найдите бит, который отличается в этих двух числах, чтобы разделить все числа в массиве на две группы.
3️⃣ Выполните XOR для каждой группы, чтобы найти два уникальных числа.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 260. Single Number III
Дан целочисленный массив nums, в котором ровно два элемента встречаются только один раз, а все остальные элементы встречаются ровно дважды. Найдите два элемента, которые встречаются только один раз. Вы можете вернуть ответ в любом порядке.
Вы должны написать алгоритм, который работает за линейное время и использует только постоянное дополнительное пространство..
Пример:
Input: nums = [1,2,1,3,2,5]
Output: [3,5]
Explanation: [5, 3] is also a valid answer.
public class Solution {
public int[] SingleNumber(int[] nums) {
int xor = 0;
foreach (int num in nums) {
xor ^= num;
}
int diff = xor & -xor;
int[] res = new int[2];
foreach (int num in 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 в противном случае.
Пример:
👨💻 Алгоритм:
1️⃣ Проверьте, что количество рёбер равно n - 1. Если нет, верните false.
2️⃣ Используйте итеративный обход в глубину (DFS) для проверки связности графа и отсутствия циклов. Создайте стек для хранения узлов для посещения и множество для отслеживания посещённых узлов. Начните с узла 0.
3️⃣ Если все узлы посещены и циклы не обнаружены, верните true. В противном случае, верните false.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 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
using System;
using System.Collections.Generic;
public class Solution {
public bool ValidTree(int n, int[][] edges) {
if (edges.Length != n - 1) {
return false;
}
List<int>[] adjList = new List<int>[n];
for (int i = 0; i < n; i++) {
adjList[i] = new List<int>();
}
foreach (var edge in edges) {
adjList[edge[0]].Add(edge[1]);
adjList[edge[1]].Add(edge[0]);
}
Dictionary<int, int> parent = new Dictionary<int, int> { { 0, -1 } };
Queue<int> queue = new Queue<int>();
queue.Enqueue(0);
while (queue.Count > 0) {
int node = queue.Dequeue();
foreach (int neighbor in adjList[node]) {
if (neighbor == parent[node]) {
continue;
}
if (parent.ContainsKey(neighbor)) {
return false;
}
parent[neighbor] = node;
queue.Enqueue(neighbor);
}
}
return parent.Count == n;
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
СиШарпСНуляДоПрофи.docx
88.2 MB
Парень написал обширное руководство по C# в виде формата Word, которое охватывает все основные концепции языка С# включая парадигму ООП.
Руководство еще подлежит коррективам но вы сможете уже его использовать для обучения/ознакомления и зафиксировать основные моменты. Сам документ прикреплен ниже. Выглядит очень информативно 👍
Можете оставить фидбек в коментах, ну либо кто хочет помочь совместно закончить реализацию напишите ему: https://t.iss.one/vlar4x
Руководство еще подлежит коррективам но вы сможете уже его использовать для обучения/ознакомления и зафиксировать основные моменты. Сам документ прикреплен ниже. Выглядит очень информативно 👍
Можете оставить фидбек в коментах, ну либо кто хочет помочь совместно закончить реализацию напишите ему: https://t.iss.one/vlar4x
👍5
#easy
Задача: 263. Ugly Number
Уродливое число — это положительное целое число, простые множители которого ограничены числами 2, 3 и 5.
Дано целое число n, верните true, если n является уродливым числом.
Пример:
👨💻 Алгоритм:
1️⃣ Если данное целое число n неположительное, верните false, так как неположительное число не может быть уродливым.
2️⃣ Определите функцию keepDividingWhenDivisible, которая принимает два аргумента: делимое и делитель. Эта функция будет делить делимое на делитель до тех пор, пока оно делится без остатка. Функция возвращает измененное делимое. Последовательно примените эту функцию к n с делителями 2, 3 и 5.
3️⃣ Если после всех делений n равно 1, верните true, иначе верните false.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 263. Ugly Number
Уродливое число — это положительное целое число, простые множители которого ограничены числами 2, 3 и 5.
Дано целое число n, верните true, если n является уродливым числом.
Пример:
Input: n = 6
Output: true
Explanation: 6 = 2 × 3
public class Solution {
public bool IsUgly(int n) {
if (n <= 0) {
return false;
}
foreach (int factor in new int[] {2, 3, 5}) {
n = KeepDividingWhenDivisible(n, factor);
}
return n == 1;
}
private int KeepDividingWhenDivisible(int dividend, int divisor) {
while (dividend % divisor == 0) {
dividend /= divisor;
}
return dividend;
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
#medium
Задача: 240. Search a 2D Matrix II
Напишите эффективный алгоритм, который ищет значение target в матрице целых чисел размером m на n. У этой матрицы есть следующие свойства:
Целые числа в каждой строке отсортированы по возрастанию слева направо.
Целые числа в каждом столбце отсортированы по возрастанию сверху вниз.
Пример:
👨💻 Алгоритм:
1️⃣ Проверка матрицы: Перед началом поиска убедитесь, что матрица не пуста и не содержит null.
2️⃣ Итерация по диагоналям: Итерируйте по диагоналям матрицы, используя инвариант отсортированности срезов строк и столбцов, начиная с текущей позиции (строка, столбец). Для каждого такого среза используйте бинарный поиск для нахождения целевого значения.
3️⃣ Бинарный поиск и завершение: Продолжайте бинарный поиск до тех пор, пока не исчерпаете все диагонали (в этом случае возвращается False) или пока не найдете целевое значение (в этом случае возвращается True). Функция бинарного поиска должна уметь работать как с рядами, так и с колонками матрицы.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 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
public class Solution {
private bool BinarySearch(int[,] matrix, int target, int start, bool vertical) {
int lo = start;
int hi = vertical ? matrix.GetLength(1) - 1 : matrix.GetLength(0) - 1;
while (hi >= lo) {
int mid = (lo + hi) / 2;
int value = vertical ? matrix[start, mid] : matrix[mid, start];
if (value < target) {
lo = mid + 1;
} else if (value > target) {
hi = mid - 1;
} else {
return true;
}
}
return false;
}
public bool SearchMatrix(int[,] matrix, int target) {
if (matrix == null || matrix.Length == 0) return false;
int shorterDim = Math.Min(matrix.GetLength(0), matrix.GetLength(1));
for (int i = 0; i < shorterDim; i++) {
if (BinarySearch(matrix, target, i, true) || BinarySearch(matrix, target, i, false)) {
return true;
}
}
return false;
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
#easy
Задача: 242. Valid Anagram
Даны две строки s и t, верните true, если t является анаграммой s, и false в противном случае.
Анаграмма — это слово или фраза, сформированная путём перестановки букв другого слова или фразы, обычно используя все исходные буквы ровно один раз.
Пример:
👨💻 Алгоритм:
1️⃣ Создайте массив размером 26 для подсчета частот каждой буквы (поскольку s и t содержат только буквы от 'a' до 'z').
2️⃣ Пройдитесь по строке s, увеличивая счетчик соответствующей буквы. Затем пройдитесь по строке t, уменьшая счетчик для каждой буквы.
3️⃣ Проверьте, не опустился ли счетчик ниже нуля во время обхода строки t. Если это произошло, значит в t есть лишняя буква, которой нет в s, и следует вернуть false. Если после проверки всех букв все счетчики равны нулю, возвращайте true, указывая на то, что t является анаграммой s.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 242. Valid Anagram
Даны две строки s и t, верните true, если t является анаграммой s, и false в противном случае.
Анаграмма — это слово или фраза, сформированная путём перестановки букв другого слова или фразы, обычно используя все исходные буквы ровно один раз.
Пример:
Input: s = "anagram", t = "nagaram"
Output: true
public bool IsAnagram(string s, string t) {
if (s.Length != t.Length) {
return false;
}
int[] table = new int[26];
for (int i = 0; i < s.Length; i++) {
table[s[i] - 'a']++;
table[t[i] - 'a']--;
}
foreach (int count in table) {
if (count != 0) return false;
}
return true;
}Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
#easy
Задача: 243. Shortest Word Distance
Дан массив строк
Пример:
👨💻 Алгоритм:
1️⃣ Начните с перебора всего массива для поиска первого слова. Каждый раз, когда вы находите встречу первого слова, запомните его позицию.
2️⃣ При каждом обнаружении первого слова переберите массив в поисках ближайшего вхождения второго слова, сохраняя позицию и сравнивая расстояние с предыдущими найденными.
3️⃣ Сохраняйте минимальное найденное расстояние между двумя словами и возвращайте его в качестве результата.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 243. Shortest Word Distance
Дан массив строк
wordsDict и две разные строки, которые уже существуют в массиве: word1 и word2. Верните кратчайшее расстояние между этими двумя словами в списке.Пример:
Input: wordsDict = ["practice", "makes", "perfect", "coding", "makes"], word1 = "coding", word2 = "practice"
Output: 3
public class Solution {
public int ShortestDistance(string[] words, string word1, string word2) {
int minDistance = words.Length;
for (int i = 0; i < words.Length; i++) {
if (words[i] == word1) {
for (int j = 0; j < words.Length; j++) {
if (words[j] == word2) {
minDistance = Math.Min(minDistance, Math.Abs(i - j));
}
}
}
}
return minDistance;
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 244. Shortest Word Distance II
Создайте структуру данных, которая будет инициализироваться массивом строк, а затем должна отвечать на запросы о наименьшем расстоянии между двумя разными строками из массива.
Реализуйте класс WordDistance:
WordDistance(String[] wordsDict) инициализирует объект с массивом строк wordsDict.
int shortest(String word1, String word2) возвращает наименьшее расстояние между word1 и word2 в массиве wordsDict.
Пример:
👨💻 Алгоритм:
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. Продолжайте это делать, пока все элементы в меньшем из двух массивов позиций не будут обработаны. Верните глобальное минимальное расстояние между словами.
😎 Решение:
🔥 ТОП ВОПРОСОВ С СОБЕСОВ
🔒 База собесов | 🔒 База тестовых
Задача: 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
using System;
using System.Collections.Generic;
public class WordDistance {
private Dictionary<string, List<int>> locations;
public WordDistance(string[] words) {
locations = new Dictionary<string, List<int>>();
for (int i = 0; i < words.Length; i++) {
if (!locations.ContainsKey(words[i])) {
locations[words[i]] = new List<int>();
}
locations[words[i]].Add(i);
}
}
public int Shortest(string word1, string word2) {
List<int> loc1 = locations[word1];
List<int> loc2 = locations[word2];
int l1 = 0, l2 = 0, minDiff = int.MaxValue;
while (l1 < loc1.Count && l2 < loc2.Count) {
minDiff = Math.Min(minDiff, Math.Abs(loc1[l1] - loc2[l2]));
if (loc1[l1] < loc2[l2]) {
l1++;
} else {
l2++;
}
}
return minDiff;
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM