fa
Feedback
C# | LeetCode

C# | LeetCode

رفتن به کانال در Telegram
3 289
مشترکین
اطلاعاتی وجود ندارد24 ساعت
-77 روز
-1630 روز
آرشیو پست ها
Задача: 967. Numbers With Same Consecutive Differences Сложность: medium Даны два целых числа n и k, верните массив всех целых чисел длины n, где разница между каждыми двумя последовательными цифрами равна k. Вы можете вернуть ответ в любом порядке. Учтите, что целые числа не должны начинаться с нулей. Целые числа, такие как 02 и 043, не допускаются. Пример:
Input: n = 3, k = 7
Output: [181,292,707,818,929]
Explanation: Note that 070 is not a valid number, because it has leading zeroes.
👨‍💻 Алгоритм: 1⃣Если n равно 1, верните массив от 0 до 9, так как все однозначные числа являются допустимыми. 2⃣Инициализируйте список очередей начальными цифрами от 1 до 9. 3⃣Для каждого уровня (от 1 до n-1) создайте новый список очередей, добавляя к каждому числу в текущей очереди допустимые цифры, которые удовлетворяют условию разницы k. 😎 Решение:
public class Solution {
    public int[] NumsSameConsecDiff(int N, int K) {
        if (N == 1) return Enumerable.Range(0, 10).ToArray();
        
        var queue = new List<int>(Enumerable.Range(1, 9));
        for (int level = 1; level < N; ++level) {
            var nextQueue = new List<int>();
            foreach (int num in queue) {
                int tailDigit = num % 10;
                var nextDigits = new int[] { tailDigit + K, tailDigit - K };
                
                foreach (int nextDigit in nextDigits) {
                    if (nextDigit >= 0 && nextDigit < 10) {
                        nextQueue.Add(num * 10 + nextDigit);
                    }
                }
            }
            queue = nextQueue;
        }
        
        return queue.ToArray();
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Онлайн-интенсив для ИТ-специалистов в Открытых школах Т1 Открытые школы Т1 — карьерная программа для начинающих ИТ-специалистов от ИТ-холдинга Т1. Это ИТ-интенсив без отрыва от работы и карьерный трек в Т1 для лучших выпусников. Что тебя ждет? ✅ Бесплатный онлайн-интенсив с топовыми преподавателями ✅ Практические задачи и индивидуальная обратная связь ✅ Поддержка HR и знакомство с ИТ-командами Т1 ✅ Карьерный фаст-трек: навыки для роста из джуна в мидла ✅ Реальный шанс получить оффер в ИТ-холдинг Т1 Более 1000 специалистов уже прошли этот путь — теперь твоя очередь! Подавай заявку до 11 апреля и приходи учиться! Старт ИТ-интенсива уже 14 апреля. Подать заявку #реклама 16+ t1.ru О рекламодателе

Задача: 1146. Snapshot Array Сложность: medium Реализуйте SnapshotArray, который поддерживает следующий интерфейс: SnapshotArray(int length) инициализирует структуру данных, похожую на массив, с заданной длиной. Изначально каждый элемент равен 0. void set(index, val) устанавливает элемент с заданным индексом равным val. int snap() делает снимок массива и возвращает snap_id: общее количество вызовов snap() минус 1. int get(index, snap_id) возвращает значение на заданном индексе в момент, когда мы сделали снимок с указанным snap_id. Пример:
Input: ["SnapshotArray","set","snap","set","get"]
[[3],[0,5],[],[0,6],[0,0]]
Output: [null,null,0,null,5]
Explanation: 
SnapshotArray snapshotArr = new SnapshotArray(3); // set the length to be 3
snapshotArr.set(0,5);  // Set array[0] = 5
snapshotArr.snap();  // Take a snapshot, return snap_id = 0
snapshotArr.set(0,6);
snapshotArr.get(0,0);  // Get the value of array[0] with snap_id = 0, return 5
👨‍💻 Алгоритм: 1⃣Инициализация: Для каждого элемента nums[i] в массиве создайте пустой список для хранения его исторических значений в формате [snap_id, value]. Инициализируйте каждый список, добавив первую запись [0, 0]. 2⃣Метод set: Добавьте историческую запись [snap_id, value] в список записей historyRecords[index]. 3⃣Методы snap и get: Метод snap возвращает snap_id и увеличивает его на 1. Метод get использует бинарный поиск, чтобы найти индекс последней вставки snap_id в данный снимок (целевой индекс будет snap_index - 1). Возвращает historyRecords[index][snap_index - 1][1]. 😎 Решение:
public class SnapshotArray {
    private int snapId = 0;
    private List<SortedDictionary<int, int>> historyRecords;
    
    public SnapshotArray(int length) {
        historyRecords = new List<SortedDictionary<int, int>>(length);
        for (int i = 0; i < length; i++) {
            historyRecords.Add(new SortedDictionary<int, int> { { 0, 0 } });
        }
    }

    public void Set(int index, int val) {
        historyRecords[index][snapId] = val;
    }

    public int Snap() {
        return snapId++;
    }

    public int Get(int index, int snapId) {
        var record = historyRecords[index];
        while (snapId >= 0) {
            if (record.ContainsKey(snapId)) {
                return record[snapId];
            }
            snapId--;
        }
        return 0;
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Март с PostgreSQL — время для новых знаний! ✨ Март — идеальное время для роста! Предлагаем погрузиться в мир PostgreSQL и про
Март с PostgreSQL — время для новых знаний! ✨ Март — идеальное время для роста! Предлагаем погрузиться в мир PostgreSQL и прокачать свои навыки в работе с одной из самых популярных СУБД. ✅ Почему PostgreSQL? Надежность и гибкость для любых задач. Поддержка современных технологий и стандартов. Востребованность на рынке: от стартапов до крупных корпораций. 💻 Для кого это акция? Начинающие специалисты по базам данных. Разработчики, аналитики, DevOps, QA и BI-специалисты. Предприниматели, которые хотят лучше понимать свои данные. 📚 Что вас ждет? Практические знания для работы с PostgreSQL. Советы от экспертов и реальные кейсы. Возможность выделиться на рынке труда. ⚡ Не упустите шанс стать востребованным специалистом! Узнайте подробности акции и начните свой путь к новым знаниям уже сегодня. Узнать больше #реклама 16+ rdtex.ru О рекламодателе

Задача: 1248. Count Number of Nice Subarrays Сложность: medium Вам даны две строки s1 и s2 одинаковой длины, состоящие только из букв "x" и "y". Ваша задача - сделать эти две строки равными друг другу. Вы можете поменять местами любые два символа, принадлежащие разным строкам, что означает: поменять местами s1[i] и s2[j]. Верните минимальное количество обменов, необходимое для того, чтобы сделать s1 и s2 равными, или верните -1, если это невозможно сделать. Пример:
Input: arr = [1,2]
Output: 2
👨‍💻 Алгоритм: 1⃣Преобразуйте массив чисел nums, заменив все чётные числа на 0, а все нечётные числа на 1. 2⃣Используя технику скользящего окна (или двух указателей), найдите все подмассивы, содержащие ровно k единиц. 3⃣Подсчитайте количество таких подмассивов и верните этот результат. 😎 Решение:
public class Solution {
    public int NumberOfSubarrays(int[] nums, int k) {
        return AtMost(nums, k) - AtMost(nums, k - 1);
    }

    private int AtMost(int[] nums, int k) {
        int res = 0, left = 0, count = 0;
        for (int right = 0; right < nums.Length; right++) {
            if (nums[right] % 2 == 1) count++;
            while (count > k) {
                if (nums[left++] % 2 == 1) count--;
            }
            res += right - left + 1;
        }
        return res;
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Ищешь высокооплачиваемые проекты? Попробуй SkillStaff SkillStaff — это платформа для ИТ-специалистов, менеджеров и креаторов,
Ищешь высокооплачиваемые проекты? Попробуй SkillStaff SkillStaff — это платформа для ИТ-специалистов, менеджеров и креаторов, которым мало одного оклада. Здесь можно найти клиентов, выполнять их проекты и увеличивать свой доход. - Проекты с гибким графиком: part time, full time, удаленка и гибрид - Ставка за час работы — та, что ты сам выбрал - Клиенты — ведущие бренды, проверенные с юридической точки зрения при регистрации на платформе - Оплата поступает ежемесячно на расчетный счет исполнителя - Удобный личный кабинет и функционал, автоматизирующий документооборот Все, что нужно для работы — иметь статус самозанятого или ИП, а платформа поможет со всеми нюансами. Регистрируйся прямо сейчас Зарегистрироваться #реклама 16+ skillstaff.ru О рекламодателе

Задача: 1167. Minimum Cost to Connect Sticks Сложность: medium У вас есть несколько палочек с положительными целыми длинами. Эти длины даны в виде массива sticks, где sticks[i] — длина i-й палочки. Вы можете соединить любые две палочки длиной x и y в одну палочку, заплатив стоимость x + y. Вы должны соединить все палочки, пока не останется только одна палочка. Верните минимальную стоимость соединения всех данных палочек в одну палочку таким образом. Пример:
Input: sticks = [5]
Output: 0
Explanation: There is only one stick, so you don't need to do anything. The total cost is 0.
👨‍💻 Алгоритм: 1⃣Всегда выбирайте две самые маленькие палочки для соединения и продолжайте делать это, пока не останется только одна палочка. Рассмотрим 4 палочки следующих длин: sticks=[a1, a2, a3, a4]. Попробуем соединить их слева направо. После первого соединения у нас будет: sticks=[(a1 + a2), a3, a4], стоимость=(a1 + a2). После второго соединения у нас будет: sticks=[(a1 + a2 + a3), a4], стоимость=(a1 + a2)+(a1 + a2 + a3). И, наконец, последняя палочка будет выглядеть так: sticks=[(a1 + a2 + a3 + a4)], стоимость=(a1 + a2)+(a1 + a2 + a3)+(a1 + a2 + a3 + a4). 2⃣Итоговая стоимость может быть переписана следующим образом: стоимость=(3a1 + 3a2 + 2a3 + a4). Как видим, палочки, которые соединяются первыми, включаются в итоговую стоимость больше, чем те, которые выбираются позже. Следовательно, оптимально сначала выбирать меньшие палочки, чтобы получить наименьшую стоимость. 3⃣Для выполнения следующих задач будет оптимальна структура данных min heap (которая обычно реализуется как PriorityQueue в большинстве языков): получить две самые маленькие палочки (stick1 и stick2) из массива; добавить одну палочку (stick1 + stick2) обратно в массив. Эта структура данных дает сложность O(logN) для обеих операций. 😎 Решение:
using System;
using System.Collections.Generic;

public class Solution {
    public int ConnectSticks(int[] sticks) {
        int totalCost = 0;
        PriorityQueue<int, int> pq = new PriorityQueue<int, int>();
        
        foreach (int stick in sticks) {
            pq.Enqueue(stick, stick);
        }
        
        while (pq.Count > 1) {
            int stick1 = pq.Dequeue();
            int stick2 = pq.Dequeue();
            int cost = stick1 + stick2;
            totalCost += cost;
            pq.Enqueue(cost, cost);
        }
        
        return totalCost;
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Создаем кастом Casio G-Shock! ⚡ Большой выбор кастомных часов Casio для него и для нее. ⚡ Гарантия качества, индивидуальный подход, рассрочка! Создай часы под свой стиль в нашем конфигураторе! Узнать больше #реклама click.tgtrack.ru О рекламодателе

Задача: 1326. Minimum Number of Taps to Open to Water a Garden Сложность: hard Есть одномерный сад на оси x. Сад начинается в точке 0 и заканчивается в точке n. (т.е. длина сада равна n). В саду есть n + 1 кранов, расположенных в точках [0, 1, ..., n]. Даны целое число n и целочисленный массив ranges длиной n + 1, где ranges[i] (индексация начинается с 0) означает, что i-й кран может поливать область [i - ranges[i], i + ranges[i]], если он открыт. Верните минимальное количество кранов, которые должны быть открыты для полива всего сада. Если сад невозможно полить, верните -1. Пример:
Input: n = 5, ranges = [3,4,1,1,0,0]
Output: 1
Explanation: The tap at point 0 can cover the interval [-3,3]
The tap at point 1 can cover the interval [-3,5]
The tap at point 2 can cover the interval [1,3]
The tap at point 3 can cover the interval [2,4]
The tap at point 4 can cover the interval [4,4]
The tap at point 5 can cover the interval [5,5]
Opening Only the second tap will water the whole garden [0,5]
👨‍💻 Алгоритм: 1⃣Объявите массив dp размера n+1. Инициализируйте его значениями бесконечности (в коде используем большое число 10^9 для представления бесконечности). Установите dp[0] в 0 (базовый случай DP). 2⃣Итерируйтесь от i до n (через каждый кран слева направо). Рассчитайте самую левую позицию, достижимую текущим краном, как tap_start=max(0,i−ranges[i]). И самую правую позицию tap_end=min(n,i+ranges[i]). 3⃣Итерируйтесь через позиции j от tap_start до tap_end (в пределах досягаемости крана). Обновите dp[tap_end] значением dp[j]+1, если оно меньше. Если dp[n] остается бесконечным, значит, полить весь сад невозможно, и мы возвращаем −1. Верните dp[n]. 😎 Решение:
public class Solution {
    public int MinTaps(int n, int[] ranges) {
        const int INF = int.MaxValue;
        int[] dp = new int[n + 1];
        Array.Fill(dp, INF);
        dp[0] = 0;
        
        for (int i = 0; i <= n; i++) {
            int tapStart = Math.Max(0, i - ranges[i]);
            int tapEnd = Math.Min(n, i + ranges[i]);
            
            for (int j = tapStart; j <= tapEnd; j++) {
                dp[tapEnd] = Math.Min(dp[tapEnd], dp[j] + 1);
            }
        }
        
        return dp[n] == INF ? -1 : dp[n];
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Методичка: как сделать онлайн-встречи эффективнее Надоело ждать коллег, которые постоянно забывают о встречах, а отсутствие п
Методичка: как сделать онлайн-встречи эффективнее Надоело ждать коллег, которые постоянно забывают о встречах, а отсутствие повестки и потерянные договоренности мешают нормально работать? Команда МТС Линк собрала на 37 страницах полезные материалы, чек-листы и кейсы, которые помогают компаниям проводить эффективные совещания в онлайне с помощью сервиса Встречи. Из методички узнаете: - Как создать постоянную ссылку и подключаться на встречи в 2 клика, - Как делать заметки и работать с файлами, не переживая за качество связи и безопасность данных. - Как облегчает жизнь ИИ, который расшифровывает созвоны в текст и автоматически отправляет расшифровку на почту. Еще в методичке описаны 7 способов оценки текущей эффективности ваших онлайн-встреч. Получить гайд можно бесплатно на сайте. Скачать #реклама 16+ mts-link.ru О рекламодателе

Repost from easyoffer
Я поставил целью сбора скромные 300 тыс. рублей, но ребята, вы накидали больше млн. всего за 1 день. Это просто невероятно! Б
Я поставил целью сбора скромные 300 тыс. рублей, но ребята, вы накидали больше млн. всего за 1 день. Это просто невероятно! Благодаря вашей поддержке, я смогу привлечь еще больше людей для разработки сайта и обработки собеседований. Ваш вклад сделает проект качественнее и ускорит его выход! Огромное вам спасибо! Краудфандинг будет продолжаться еще 31 день и все кто поддержать проект сейчас, до его выхода, смогут получить: 🚀 PRO-тариф на 1 год, по цене месячной подписки на релизе. ➕ Доступ к закрытому бета-тесту easyoffer 2.0 (середина–конец мая) Поддержать проект можно здесь: https://planeta.ru/campaigns/easyoffer Огромное спасибо за вашу поддержку! 🤝

Большая онлайн-конференция UserGate OpenConfИТ-конференция про защиту в открытую. Диалог между заказчиками, партнерами, экспертами и специалистами в сфере продуктов, технологий и услуг информационной безопасности. Зарегистрироваться #реклама 16+ openconf.usergate.com О рекламодателе

Repost from easyoffer
🎉 Краудфандинг easyoffer 2.0 стартовал! Друзья, с этого момента вы можете поддержать проект и получить существенный бонус: �
🎉 Краудфандинг easyoffer 2.0 стартовал! Друзья, с этого момента вы можете поддержать проект и получить существенный бонус: 🚀 PRO-тариф на 1 год, по цене месячной подписки на релизе. ➕ Доступ к закрытому бета-тесту easyoffer 2.0 (середина–конец мая) Поддержать проект можно здесь: https://planeta.ru/campaigns/easyoffer 📌 Если не получается оплатить через карту РФ — напишите мне @kivaiko, и мы найдём удобный способ

Задача: 1424. Diagonal Traverse II Сложность: medium Дан двумерный целочисленный массив nums, верните все элементы nums в диагональном порядке. Пример:
Input: nums = [[1,2,3,4,5],[6,7],[8],[9,10,11],[12,13,14,15,16]]
Output: [1,6,2,8,7,3,9,4,12,10,5,13,11,14,15,16]
👨‍💻 Алгоритм: 1⃣Инициализируйте очередь с (0, 0) и список ответов ans. 2⃣Пока очередь не пуста: Извлеките (row, col) из очереди. Добавьте nums[row][col] в ans. Если col == 0 и row + 1 в пределах массива, добавьте (row + 1, col) в очередь. Если col + 1 в пределах текущей строки, добавьте (row, col + 1) в очередь. 3⃣Верните ans. 😎 Решение:
public class Solution {
    public int[] FindDiagonalOrder(IList<IList<int>> nums) {
        var queue = new Queue<(int row, int col)>();
        queue.Enqueue((0, 0));
        var ans = new List<int>();
        
        while (queue.Count > 0) {
            var (row, col) = queue.Dequeue();
            ans.Add(nums[row][col]);
            
            if (col == 0 && row + 1 < nums.Count) {
                queue.Enqueue((row + 1, col));
            }
            
            if (col + 1 < nums[row].Count) {
                queue.Enqueue((row, col + 1));
            }
        }
        
        return ans.ToArray();
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Качаем скиллы PostgreSQL на PG BootCamp Russia 2025! Регистрируйся на бесплатную конференцию по PostgreSQL — 10.04.2025.📅 ✅
Качаем скиллы PostgreSQL на PG BootCamp Russia 2025! Регистрируйся на бесплатную конференцию по PostgreSQL — 10.04.2025.📅 ✅ Бесплатное участие ✅ Опытные спикеры ✅ Тематические доклады ✅ Рабочие кейсы Каждый участник получает именной Сертификат участника мероприятия. Одни из немногих спикеров конференции: — Андрей Бородин PostgreSQL contributor, руководитель подразделения разработки РСУБД с открытым исходным кодом Yandex Cloud — Александр Никитин Ведущий администратор БД DBA.Team — Максим Милютин PostgreSQL Contributor, openGauss Contributor ... и многие другие. Регистрируйся, будет интересно! И бесплатно! Зарегистрироваться #реклама pgbootcamp.ru О рекламодателе

Задача: 991. Broken Calculator Сложность: medium Имеется неисправный калькулятор, на экране которого изначально отображается целое число startValue. За одну операцию можно: Умножить число на экране на 2, или Вычесть 1 из числа на экране. Даны два целых числа startValue и target. Верните минимальное количество операций, необходимых для отображения target на калькуляторе. Пример:
Input: startValue = 2, target = 3
Output: 2
Explanation: Use double operation and then decrement operation {2 -> 4 -> 3}.
👨‍💻 Алгоритм: 1⃣Обратный путь: Если target больше startValue, то попытайтесь уменьшить target, чтобы привести его к startValue. Если target четный, разделите его на 2, иначе прибавьте 1. 2⃣Подсчет операций: Повторяйте шаги, пока target не станет меньше или равен startValue. После этого вычитайте из startValue оставшееся значение target. 3⃣Возврат результата: Возвращайте суммарное количество выполненных операций. 😎 Решение:
public class Solution {
    public int BrokenCalc(int startValue, int target) {
        int operations = 0;
        
        while (target > startValue) {
            operations++;
            if (target % 2 == 0) {
                target /= 2;
            } else {
                target += 1;
            }
        }
        
        return operations + (startValue - target);
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Задача: 687. Longest Univalue Path Сложность: medium Дано корень бинарного дерева, верните длину самого длинного пути, на котором все узлы имеют одинаковое значение. Этот путь может проходить через корень или не проходить. Длина пути между двумя узлами представлена количеством рёбер между ними. Пример:
Input: root = [5,4,5,1,1,null,5]
Output: 2
Explanation: The shown image shows that the longest path of the same value (i.e. 5).
👨‍💻 Алгоритм: 1⃣Определить рекурсивную функцию solve(), принимающую текущий узел root и значение родительского узла parent. Если root равен NULL, вернуть 0. Рекурсивно вызвать solve() для левого и правого дочернего узлов, передав значение текущего узла как значение родительского узла. 2⃣Обновить переменную ans, если сумма значений для левого и правого узлов больше текущего значения ans. Если значение текущего узла равно значению родительского узла, вернуть max(left, right) + 1, иначе вернуть 0. 3⃣Вызвать solve() с корневым узлом и значением родительского узла -1. Вернуть максимальную длину пути ans.. 😎 Решение:
public class Solution {
    private int ans = 0;

    private int Solve(TreeNode root, int parent) {
        if (root == null) {
            return 0;
        }

        int left = Solve(root.left, root.val);
        int right = Solve(root.right, root.val);
        
        ans = Math.Max(ans, left + right);
        
        return root.val == parent ? Math.Max(left, right) + 1 : 0;
    }

    public int LongestUnivaluePath(TreeNode root) {
        Solve(root, -1);
        return ans;
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Почему вы не используете Битрикс24 CRM с AI-помощником? 1- не знал 2- забыл Рассказываем и напоминаем! ✅Битрикс24 CRM с AI помогает увеличивать продажи, работать с постоянными клиентами и сохранять все важные данные. AI-помощник CoPilot внутри сервиса расшифрует телефонные разговоры и автоматически заполнит карточки клиента в CRM. Битрикс24 можно использовать бесплатно для всех команд, независимо от их размера. ⚡Не тратьте время на рутину. Узнать больше #реклама 16+ bitrix24.ru О рекламодателе

Задача: 56. Merge Intervals Сложность: medium Дан массив интервалов intervals, где intervals[i] = [start_i, end_i]. Нужно объединить все перекрывающиеся интервалы и вернуть массив неперекрывающихся интервалов. Пример:
Input: intervals = [[1,3],[2,6],[8,10],[15,18]]  
Output: [[1,6],[8,10],[15,18]]  
Explanation: Так как `[1,3]` и `[2,6]` пересекаются, объединяем их в `[1,6]`.  
👨‍💻 Алгоритм: 1⃣Отсортировать интервалы по start. 2⃣Использовать List<int[]> merged, добавляя в него первый интервал. 3⃣Пройтись по остальным интервалам: - Если current.start <= lastMerged.end, объединить интервалы. - Иначе добавить current в merged. 4⃣Вернуть merged как int[][]. 😎 Решение:
public class Solution {
    public int[][] Merge(int[][] intervals) {
        if (intervals.Length == 0) return new int[0][];

        Array.Sort(intervals, (a, b) => a[0] - b[0]);
        List<int[]> merged = new List<int[]>();

        foreach (var interval in intervals) {
            if (merged.Count == 0 || merged[^1][1] < interval[0]) {
                merged.Add(interval);
            } else {
                merged[^1][1] = Math.Max(merged[^1][1], interval[1]);
            }
        }

        return merged.ToArray();
    }
}
Ставь 👍 и забирай 📚 Базу знаний

Repost from easyoffer
На easyoffer 2.0 появится: База тестовых заданий 🟠Тестовые задания для разных грейдов 🟠Фильтрация тестовых заданий по техно
На easyoffer 2.0 появится: База тестовых заданий 🟠Тестовые задания для разных грейдов 🟠Фильтрация тестовых заданий по технологиям и компаниям Когда я только начинал учиться на программиста, я постоянно выдумывал себе задачи для практики и тратил на это много времени. Но только в момент поиска работы я столкнулся с тестовыми заданиями, и понял насколько круто они прокачивают навыки. Нужно было еще на этапе обучения пробовать их делать. Все компании стараются составить тестовое задание "под себя", это дает большой выбор в тематике задач и технологий. На easyoffer 2.0 вы сможете отфильтровать тестовые задания по навыкам/грейдам и найти те, что подходят лично вам для практики. В течение 1-2 дней я объявлю о краудфандинг кампании, чтобы ускорить разработку easyoffer 2.0. Все кто, поддержал проект на этом этапе смогу получить 1 год доступа к сайту по цене месячной подписки и смогут попасть на закрытое бета-тестирование. А первые 150 донатеров получать особо-выгодную цену и бонус. 🚀 Следите за стартом 👉 в этом телеграм канале, в нем информация о старте будет опубликована за 6 часов до официального начала.