Библиотека шарписта | C#, F#, .NET, ASP.NET
22.6K subscribers
2.41K photos
39 videos
85 files
4.6K links
Все самое полезное для C#-разработчика в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/b60af5a4

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Download Telegram
⚙️ Когда Hash Join быстрее Nested Loops

Внутри SQL-движка соединение таблиц — это не магия, а конкретный алгоритм. Сравним два подхода к соединению таблиц.

Nested Loops работает буквально так, как звучит: берём строку из первой таблицы и ищем совпадения во второй. Если вторая таблица имеет подходящий индекс, поиск по нему будет очень быстрым, и такой алгоритм блестяще справляется с задачей маленькое соединяется с большим.

Hash Join подходит там, где Nested Loops захлёбывается. Он сначала строит хэш-таблицу по одной из входных таблиц, а затем пробегается по второй и ищет совпадения через хэш-функцию. Это даёт огромный выигрыш, когда нужно соединить два больших набора данных, и когда индексов для ускорения поиска нет. Цена такого подхода — расход памяти.

В итоге — если речь идёт о маленьком наборе строк против большого и есть индекс, Nested Loops окажется быстрее. Но если обе таблицы крупные и индексы не спасают, Hash Join чаще всего становится оптимальным выбором.

💬 Как вы бы ответили на такой вопрос на собеседовании?

🐸Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91
Что выведет код

Пишите свои ответы в комментариях 👇

Для любознательных ответ такой: 333

🐸Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
🚩 Задача с собеса: пират и сундуки

Представьте, что вы пират и у вас есть 12 закрытых сундуков. Все они полны золотых монет, но один — фейковый: в нём только песок. Золото тяжелее, песок легче. У вас есть большие весы без гирь, и всего три взвешивания, чтобы вычислить пустышку.

Как решить эту задачу:

1. Делим сундуки на группы по 6 штук. Взвешиваем. Берём ту группу, где вес меньше.

2. Снова делим на группы, но теперь по 3. Взвешиваем. Берём ту тройку, где легче.

3. Сравниваем внутри этой тройки два сундука. Лёгкий сундук и будет с песком. Если сундуки одинаковые по весу, но с песком тот, что остался.

Задача решается бинарным поиском.

🐸 Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍234👏4😁2
💪 Разминка перед выходными

Есть код:
var dict = new Dictionary<object, string>();

dict[1] = "int";
dict[1L] = "long";
dict[1.0] = "double";

Console.WriteLine(dict.Count);
Console.WriteLine(dict[1 ]);


Что выведет код? Пишите в комменты 👇

Ответь спрячем здесь:
3
int


🐸 Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🤔52
🚩 Задача с собеса: контейнер с водой

Ваша задача — выбрать две вертикальные линии на плоскости, чтобы вместе с осью X они образовали контейнер, в который поместится максимум воды. Даны высоты этих линий в массиве.

Как действовать:

1. Ставим два указателя: один — на начало, второй — на конец массива.

2. Считаем объем текущего контейнера: ширина между указателями умножается на минимальную из двух высот.

3. Двигаем указатель с меньшей высотой внутрь. Если обе высоты равны — можно сдвигать любой.

4. Запоминаем максимум, повторяем шаги, пока указатели не встретятся.

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

Пример реализации:
public int MaxArea(int[] h)
{
int l = 0, r = h.Length - 1, m = 0;
while (l < r)
{
m = Math.Max(m, (r - l) * Math.Min(h[l], h[r]));
if (h[l] < h[r]) l++; else r--;
}
return m;
}


➡️ Попробовать на литкоде

🐸 Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍82
✏️ Задача с собеса: квадраты отсортированного массива

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

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

1. Обрабатываем два края массива (left и right), сравниваем их квадраты.

2. Наибольший квадрат записываем в конец результирующего массива.

3. Сдвигаем соответствующий указатель — либо left, либо right.

4. В конце получаем отсортированный массив квадратов.

Решение с двумя указателями:
public int[] SortedSquares(int[] nums) {
int n = nums.Length;
int[] result = new int[n];
int left = 0, right = n - 1, pos = n - 1;

while (left <= right) {
int leftSq = nums[left] * nums[left];
int rightSq = nums[right] * nums[right];

if (leftSq > rightSq) {
result[pos] = leftSq;
left++;
} else {
result[pos] = rightSq;
right--;
}
pos--;
}
return result;
}


➡️ Попробовать на литкоде

🐸 Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
7❤‍🔥6🥱2
🚩 Задача с собеса

Задача: дана строка s и строка p. Необходимо найти все начальные индексы подстрок в s, которые являются анаграммами строки p.

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

Пример:
Input: s = "cbaebabacd", p = "abc"
Output: [0, 6]

Объяснение:
Подстрока с индекса 0 - "cba", анаграмма "abc".
Подстрока с индекса 6 - "bac", анаграмма "abc".


Оптимальное решение использует технику скользящего окна с подсчетом частот символов.

1. Подсчитываем количество и частоту всех символов в строке p
2. Создаем скользящее окно размером со строку p в строке s
3. Для каждой позиции окна сравниваем частоты символов с эталоном
4. При совпадении добавляем индекс в результат

Код:
public class Solution 
{
public IList<int> FindAnagrams(string s, string p)
{
List<int> result = new List<int>();

if (s.Length < p.Length)
return result;

// Массивы для подсчета частот символов (26 букв английского алфавита)
int[] pCount = new int[26];
int[] windowCount = new int[26];

// Подсчитываем частоты в строке p и первом окне
for (int i = 0; i < p.Length; i++)
{
pCount[p[i] - 'a']++;
windowCount[s[i] - 'a']++;
}

// Проверяем первое окно
if (AreEqual(pCount, windowCount))
result.Add(0);

// Скользим окном по строке s
for (int i = p.Length; i < s.Length; i++)
{
// Добавляем новый символ справа
windowCount[s[i] - 'a']++;

// Удаляем старый символ слева
windowCount[s[i - p.Length] - 'a']--;

// Проверяем текущее окно
if (AreEqual(pCount, windowCount))
result.Add(i - p.Length + 1);
}

return result;
}

// Вспомогательный метод для сравнения массивов частот
private bool AreEqual(int[] arr1, int[] arr2)
{
for (int i = 0; i < 26; i++)
{
if (arr1[i] != arr2[i])
return false;
}
return true;
}
}


🐸 Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩32🔥2💯2👾2
🔄 Как развернуть связный список

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

У вас есть цепочка узлов: 1 → 2 → 3 → 4 → 5. Каждый узел хранит значение и ссылку на следующий элемент. Задача — перевернуть все стрелки: 1 ← 2 ← 3 ← 4 ← 5.

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

Итеративное решение: три указателя

Самый надёжный подход — использовать три указателя, которые двигаются по списку синхронно.

• prev отслеживает предыдущий узел
• curr указывает на текущий обрабатываемый узел
• next сохраняет следующий узел, чтобы не потерять его при развороте

Код:
public ListNode ReverseList(ListNode head)
{
ListNode prev = null;
ListNode curr = head;

while (curr != null)
{
ListNode next = curr.next; // сохраняем следующий
curr.next = prev; // разворачиваем стрелку
prev = curr; // двигаем prev
curr = next; // двигаем curr
}

return prev;
}


Рекурсивное решение

Если вам нравятся рекурсивные решения, есть и такой вариант:
public ListNode ReverseList(ListNode head)
{
if (head == null || head.next == null)
return head;

ListNode newHead = ReverseList(head.next);
head.next.next = head;
head.next = null;

return newHead;
}


Попробуйте решить задачу сами, прежде чем смотреть готовый код. Нарисуйте список на бумаге, отследите движение указателей вручную. Это единственный способ понять, что происходит.

➡️ Решить задачу

🐸 Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7🙏2👾1
✏️ Как заработать на всех взлётах цены акций

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

Пример:
Цены: [7, 1, 5, 3, 6, 4]
Ответ: 7

Покупаем за 1, продаём за 5 (прибыль 4). Покупаем за 3, продаём за 6 (прибыль 3). Итого — 7.

Алгоритм

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

Представьте график цен: вам нужно получить прибыль со всех участков, где график идёт вверх. Неважно, сколько это будет сделок — каждый рост приносит деньги.

Почему это работает

Если цена растёт три дня подряд (например, 1 → 3 → 5), то неважно, продавать ли каждый день или держать до конца.

Код:
public class Solution 
{
public int MaxProfit(int[] prices)
{
if (prices == null || prices.Length < 2)
return 0;

int totalProfit = 0;

for (int i = 1; i < prices.Length; i++)
{
// Если цена выросла — берём эту прибыль
if (prices[i] > prices[i - 1])
{
totalProfit += prices[i] - prices[i - 1];
}
}

return totalProfit;
}
}


Или ещё компактнее:
public class Solution 
{
public int MaxProfit(int[] prices)
{
int profit = 0;

for (int i = 1; i < prices.Length; i++)
{
profit += Math.Max(0, prices[i] - prices[i - 1]);
}

return profit;
}
}


Жадный подход здесь безупречен: захватываем каждый рост, игнорируем падения. Никаких сложных расчётов оптимальных точек — только простая логика и максимальная прибыль.

➡️ Попробовать решить

Чтобы щёлкать такие задачи нужно знать алгоритмы. Подтянуть такую базу поможет наш курс по алгоритмам. До конца октября скидка 40%

🐸 Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
😁6👍1