ch
Feedback
C/C++ | LeetCode

C/C++ | LeetCode

前往频道在 Telegram

Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv

显示更多
3 238
订阅者
+424 小时
+127
+230
帖子存档
Задача: 1005. Maximize Sum Of Array After K Negations Сложность: easy Учитывая целочисленный массив nums и целое число k, измените массив следующим образом: выберите индекс i и замените nums[i] на -nums[i]. Вы должны применить этот процесс ровно k раз. Вы можете выбрать один и тот же индекс i несколько раз. Верните наибольшую возможную сумму массива после его модификации таким образом. Пример:
Input: nums = [4,2,3], k = 1
Output: 5
👨‍💻 Алгоритм: 1⃣Сортировка массива: Отсортируйте массив nums по возрастанию, чтобы наибольшее количество раз менять самые маленькие (отрицательные) значения на их противоположные. 2⃣Модификация массива: Пройдитесь по отсортированному массиву и замените k наименьших значений на их противоположные (умножьте на -1). Если встретите 0, прекратите дальнейшие изменения, так как изменение 0 на -0 не имеет смысла. 3⃣Проверка остатка изменений: Если после первого прохода остались изменения (k нечетное), то найдите минимальное значение в измененном массиве и еще раз поменяйте его знак. Это обеспечит максимальную сумму. 😎 Решение:
class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());
        
        for (int i = 0; i < nums.size(); ++i) {
            if (k > 0 && nums[i] < 0) {
                nums[i] = -nums[i];
                --k;
            }
        }
        
        if (k % 2 == 1) {
            sort(nums.begin(), nums.end());
            nums[0] = -nums[0];
        }
        
        return accumulate(nums.begin(), nums.end(), 0);
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 96. Unique Binary Search Trees Сложность: medium Дано число n. Нужно вычислить количество структурно уникальных бинар
Задача: 96. Unique Binary Search Trees Сложность: medium Дано число n. Нужно вычислить количество структурно уникальных бинарных деревьев поиска (BST), состоящих из n узлов с уникальными значениями от 1 до n. Пример:
Input: n = 3
Output: 5
👨‍💻 Алгоритм: 1⃣Обозначим G(n) — количество уникальных BST, построенных из n узлов. Пусть F(i, n) — количество BST, в которых i является корнем. Тогда: G(n) = F(1, n) + F(2, n) + ... + F(n, n) 2⃣Для фиксированного i: в левой части — i - 1 узел, в правой — n - i. Т.е. F(i, n) = G(i - 1) * G(n - i) 3⃣Тогда: G(n) = ∑ G(i - 1) * G(n - i), i = 1..n Сохраняем значения G[0] = 1 и G[1] = 1, и далее строим по формуле. 😎 Решение:
class Solution {
public:
    int numTrees(int n) {
        vector<int> G(n + 1, 0);
        G[0] = 1;
        G[1] = 1;

        for (int i = 2; i <= n; ++i) {
            for (int j = 1; j <= i; ++j) {
                G[i] += G[j - 1] * G[i - j];
            }
        }

        return G[n];
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 743. Network Delay Time Сложность: medium Дана сеть из узлов, помеченных от 1 до n. Также дано times - список времен
Задача: 743. Network Delay Time Сложность: medium Дана сеть из узлов, помеченных от 1 до n. Также дано times - список времен прохождения сигнала в виде направленных ребер times[i] = (ui, vi, wi), где ui - исходный узел, vi - целевой узел, а wi - время прохождения сигнала от источника до цели. Мы пошлем сигнал из заданного узла k. Верните минимальное время, которое потребуется всем узлам, чтобы получить сигнал. Если все узлы не могут получить сигнал, верните -1. Пример:
Input: times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
Output: 2
👨‍💻 Алгоритм: 1⃣Представьте граф в виде списка смежности. 2⃣Используйте алгоритм Дейкстры для нахождения кратчайших путей от узла k до всех других узлов. 3⃣Найдите максимальное значение среди кратчайших путей к узлам. Если какой-либо узел недостижим, верните -1. 😎 Решение:
class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int n, int k) {
        unordered_map<int, vector<pair<int, int>>> graph;
        for (int i = 1; i <= n; ++i) {
            graph[i] = vector<pair<int, int>>();
        }
        for (auto& time : times) {
            graph[time[0]].emplace_back(time[1], time[2]);
        }

        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> minHeap;
        minHeap.emplace(0, k);
        unordered_map<int, int> minTime;
        for (int i = 1; i <= n; ++i) {
            minTime[i] = INT_MAX;
        }
        minTime[k] = 0;

        while (!minHeap.empty()) {
            auto [time, node] = minHeap.top(); minHeap.pop();
            for (auto& [neighbor, t] : graph[node]) {
                int newTime = time + t;
                if (newTime < minTime[neighbor]) {
                    minTime[neighbor] = newTime;
                    minHeap.emplace(newTime, neighbor);
                }
            }
        }

        int maxTime = *max_element(minTime.begin(), minTime.end());
        return maxTime == INT_MAX ? -1 : maxTime;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 643. Maximum Average Subarray I Сложность: easy Вам дан целочисленный массив nums, состоящий из n элементов, и целое число k. Найдите смежный подмассив, длина которого равна k и который имеет максимальное среднее значение, и верните это значение. Принимается любой ответ с погрешностью вычислений менее 10-5. Пример:
Input: nums = [1,12,-5,-6,50,3], k = 4
Output: 12.75000
👨‍💻 Алгоритм: 1⃣Инициализация скользящего окна: Вычислите сумму первых k элементов массива nums. Это будет начальное значение максимальной суммы. 2⃣Перемещение окна: Перемещайте окно длиной k по массиву, добавляя следующий элемент и убирая предыдущий, чтобы поддерживать сумму текущего окна. 3⃣Обновление максимальной суммы: На каждом шаге обновляйте максимальную сумму, если текущая сумма больше, и в конце верните среднее значение этой суммы. 😎 Решение:
class Solution {
public:
    double findMaxAverage(vector<int>& nums, int k) {
        int currentSum = accumulate(nums.begin(), nums.begin() + k, 0);
        int maxSum = currentSum;
        
        for (int i = k; i < nums.size(); i++) {
            currentSum += nums[i] - nums[i - k];
            maxSum = max(maxSum, currentSum);
        }
        
        return (double) maxSum / k;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 476. Number Complement Сложность: easy Дополнение целого числа — это число, которое получается при замене всех 0 на 1
Задача: 476. Number Complement Сложность: easy Дополнение целого числа — это число, которое получается при замене всех 0 на 1 и всех 1 на 0 в его двоичном представлении. Например, целое число 5 в двоичной системе — "101", и его дополнение — "010", что соответствует целому числу 2. Дано целое число num, верните его дополнение. Пример:
Input: num = 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.
👨‍💻 Алгоритм: 1⃣Вычислите длину в битах входного числа: l=⌊log 2 (num)⌋+1. 2⃣Постройте битовую маску из 1-битов длины l: bitmask=(1≪l)−1. 3⃣Верните результат операции XOR числа и битовой маски: num⊕bitmask num⊕bitmask. 😎 Решение:
class Solution {
public:
    int findComplement(int num) {
        int bitmask = num;
        bitmask |= (bitmask >> 1);
        bitmask |= (bitmask >> 2);
        bitmask |= (bitmask >> 4);
        bitmask |= (bitmask >> 8);
        bitmask |= (bitmask >> 16);
        return bitmask ^ num;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 244. Shortest Word Distance II Сложность: medium Необходимо реализовать структуру, которая быстро отвечает на запросы расстояния между двумя словами Пример:
Input: ["WordDistance", "shortest", "shortest"] [[["practice", "makes", "perfect", "coding", "makes"]], ["coding", "practice"], ["makes", "coding"]] Output: [null, 3, 1]
👨‍💻 Алгоритм: 1⃣В конструкторе сохраняем словарь, где каждому слову сопоставляется список индексов, на которых оно встречается в массиве 2⃣При запросе shortest(word1, word2) получаем два списка индексов и двигаемся по ним двумя указателями, считая минимальное расстояние 3⃣Возвращаем минимальное абсолютное расстояние между индексами слов 😎 Решение:
#include <vector>
#include <string>
#include <unordered_map>
#include <algorithm>

class WordDistance {
public:
    WordDistance(std::vector<std::string>& words) {
        for (int i = 0; i < words.size(); ++i) {
            locations[words[i]].push_back(i);
        }
    }

    int shortest(std::string word1, std::string word2) {
        const std::vector<int>& loc1 = locations[word1];
        const std::vector<int>& loc2 = locations[word2];
        int l1 = 0, l2 = 0, minDiff = INT_MAX;

        while (l1 < loc1.size() && l2 < loc2.size()) {
            minDiff = std::min(minDiff, std::abs(loc1[l1] - loc2[l2]));
            if (loc1[l1] < loc2[l2]) {
                ++l1;
            } else {
                ++l2;
            }
        }
        return minDiff;
    }

private:
    std::unordered_map<std::string, std::vector<int>> locations;
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 68. Text Justification Сложность: hard Дан массив слов words и ширина строки maxWidth. Необходимо вернуть текст, в котором строки выровнены по ширине с равномерным распределением пробелов, кроме последней строки — она выравнивается по левому краю. Пример:
Input: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
Output:
arduino[
   "This    is    an",
   "example  of text",
   "justification.  "
]
👨‍💻 Алгоритм: 1⃣Разделить слова на строки: жадно добавлять слова, пока их суммарная длина + пробелы не превышают maxWidth 2⃣Создать строку с выравниванием: если последняя строка или в строке одно слово — выравниваем по левому краю иначе: равномерно распределяем пробелы между словами, остаток пробелов добавляется слева 3⃣Склеить строки и вернуть результат 😎 Решение:
class Solution {
public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        vector<string> ans;
        int i = 0;
        while (i < words.size()) {
            vector<string> currentLine = getWords(i, words, maxWidth);
            i += currentLine.size();
            ans.push_back(createLine(currentLine, i, words, maxWidth));
        }
        return ans;
    }

private:
    vector<string> getWords(int i, vector<string>& words, int maxWidth) {
        vector<string> currentLine;
        int currLength = 0;
        while (i < words.size() && currLength + words[i].size() <= maxWidth) {
            currentLine.push_back(words[i]);
            currLength += words[i].size() + 1;
            i++;
        }
        return currentLine;
    }

    string createLine(vector<string>& line, int i, vector<string>& words, int maxWidth) {
        int baseLength = -1;
        for (const string& word : line) {
            baseLength += word.size() + 1;
        }
        int extraSpaces = maxWidth - baseLength;

        // Последняя строка или строка с одним словом
        if (line.size() == 1 || i == words.size()) {
            string res = join(line, " ");
            res += string(extraSpaces, ' ');
            return res;
        }

        int wordCount = line.size() - 1;
        int spacesPerWord = extraSpaces / wordCount;
        int needsExtraSpace = extraSpaces % wordCount;

        for (int j = 0; j < needsExtraSpace; j++) {
            line[j] += " ";
        }
        for (int j = 0; j < wordCount; j++) {
            line[j] += string(spacesPerWord, ' ');
        }

        return join(line, " ");
    }

    string join(vector<string>& line, const string& delimeter) {
        if (line.empty()) return "";
        string res = line[0];
        for (int i = 1; i < line.size(); i++) {
            res += delimeter + line[i];
        }
        return res;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 689. Maximum Sum of 3 Non-Overlapping Subarrays Сложность: hard Дан целочисленный массив nums и целое число k. Найдите три непересекающихся подмассива длины k с максимальной суммой и верните их. Верните результат в виде списка индексов, представляющих начальную позицию каждого интервала (нумерация с 0). Если существует несколько ответов, верните лексикографически наименьший. Пример:
Input: nums = [1,2,1,2,6,7,5,1], k = 2
Output: [0,3,5]
Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.
👨‍💻 Алгоритм: 1⃣Предположим, что фиксирован j. Нам нужно узнать на интервалах i∈[0,j−k] и l∈[j+k,len(W)−1], где наибольшее значение W[i] (и соответственно W[l]) встречается первым (то есть, с наименьшим индексом). 2⃣Мы можем решить эту задачу с помощью динамического программирования. Например, если мы знаем, что i - это место, где наибольшее значение W[i] встречается первым на [0,5], то на [0,6] первое появление наибольшего W[i] должно быть либо i, либо 6. Если, скажем, 6 лучше, тогда мы устанавливаем best = 6. В конце left[z] будет первым вхождением наибольшего значения W[i] на интервале i∈[0,z], а right[z] будет таким же, но на интервале i∈[z,len(W)−1]. 3⃣Это означает, что для некоторого выбора j, кандидат на ответ должен быть (left[j - k], j, right[j + k]). Мы выбираем кандидата, который дает максимальное значение W[i] + W[j] + W[l]. 😎 Решение:
class Solution {
public:
    vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
        vector<int> W(nums.size() - k + 1);
        int currSum = 0;
        for (int i = 0; i < nums.size(); i++) {
            currSum += nums[i];
            if (i >= k) {
                currSum -= nums[i - k];
            }
            if (i >= k - 1) {
                W[i - k + 1] = currSum;
            }
        }

        vector<int> left(W.size());
        int best = 0;
        for (int i = 0; i < W.size(); i++) {
            if (W[i] > W[best]) best = i;
            left[i] = best;
        }

        vector<int> right(W.size());
        best = W.size() - 1;
        for (int i = W.size() - 1; i >= 0; i--) {
            if (W[i] >= W[best]) best = i;
            right[i] = best;
        }
        
        vector<int> ans = {-1, -1, -1};
        for (int j = k; j < W.size() - k; j++) {
            int i = left[j - k], l = right[j + k];
            if (ans[0] == -1 || W[i] + W[j] + W[l] > W[ans[0]] + W[ans[1]] + W[ans[2]]) {
                ans = {i, j, l};
            }
        }
        return ans;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 1335. Minimum Difficulty of a Job Schedule Сложность: hard Вы хотите составить расписание списка заданий на d дней. Задания зависят друг от друга (т.е. чтобы выполнить задание i, вы должны закончить все задания j, где 0 <= j < i). Вы должны выполнять как минимум одно задание каждый день. Сложность расписания заданий — это сумма сложностей каждого дня из d дней. Сложность дня — это максимальная сложность задания, выполненного в этот день. Вам дан массив целых чисел jobDifficulty и целое число d. Сложность i-го задания равна jobDifficulty[i]. Верните минимальную сложность расписания заданий. Если вы не можете найти расписание для заданий, верните -1. Пример:
Input: jobDifficulty = [6,5,4,3,2,1], d = 2
Output: 7
Explanation: First day you can finish the first 5 jobs, total difficulty = 6.
Second day you can finish the last job, total difficulty = 1.
The difficulty of the schedule = 6 + 1 = 7 
👨‍💻 Алгоритм: 1⃣Определение состояния: Индекс i (индекс первой задачи на сегодняшний день в массиве jobDifficulty) и день d (количество оставшихся дней) будут определять состояние динамического программирования. min_diff(i, d) обозначает минимальную сложность при начале с i-й задачи с оставшимися d днями. min_diff(0, d) будет окончательным ответом, так как он представляет начало с начала массива задач и завершение всех задач за ровно d дней. 2⃣Функция перехода состояния: Задача с индексом j будет первой задачей на следующий день, следовательно, задачи, которые должны быть завершены сегодня, это все задачи с индексами между i и j, то есть jobDifficulty[i ]. Поскольку сложность дня — это максимальная сложность выполненной в этот день задачи, к сумме сложностей задач будет добавляться максимум из jobDifficulty[i ]. Формулируем функцию перехода состояния следующим образом: min_diff(i, d) = min_diff(j, d - 1) + max(jobDifficulty[i ]) для всех j > i. 3⃣Базовый случай: Когда остается только 1 день, необходимо завершить все незавершенные задачи в этот день и увеличить сложность расписания задач на максимальную сложность этих задач. 😎 Решение:
class Solution {
public:
    int minDifficulty(vector<int>& jobDifficulty, int d) {
        int n = jobDifficulty.size();
        if (n < d) {
            return -1;
        }

        vector<vector<int>> mem(n, vector<int>(d + 1, -1));
        return minDiff(0, d, jobDifficulty, mem);
    }

private:
    int minDiff(int i, int daysRemaining, vector<int>& jobDifficulty, vector<vector<int>>& mem) {
        if (mem[i][daysRemaining] != -1) {
            return mem[i][daysRemaining];
        }

        if (daysRemaining == 1) {
            int res = 0;
            for (int j = i; j < jobDifficulty.size(); j++) {
                res = max(res, jobDifficulty[j]);
            }
            return res;
        }

        int res = INT_MAX;
        int dailyMaxJobDiff = 0;
        for (int j = i; j < jobDifficulty.size() - daysRemaining + 1; j++) {
            dailyMaxJobDiff = max(dailyMaxJobDiff, jobDifficulty[j]);
            res = min(res, dailyMaxJobDiff + minDiff(j + 1, daysRemaining - 1, jobDifficulty, mem));
        }
        mem[i][daysRemaining] = res;
        return res;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 1192. Critical Connections in a Network Сложность: hard Существует n серверов, пронумерованных от 0 до n - 1, соединенных неориентированными соединениями "сервер-сервер", образуя сеть, где connections[i] = [ai, bi] представляет собой соединение между серверами ai и bi. Любой сервер может достичь других серверов напрямую или косвенно через сеть. Критическое соединение — это соединение, удаление которого сделает невозможным достижение некоторыми серверами других серверов. Верните все критические соединения в сети в любом порядке. Пример:
Input: n = 4, connections = [[0,1],[1,2],[2,0],[1,3]]
Output: [[1,3]]
Explanation: [[3,1]] is also accepted.
👨‍💻 Алгоритм: 1⃣Построение графа и инициализация: Постройте граф в виде списка смежности и создайте словарь для хранения соединений. Инициализируйте ранги для узлов. 2⃣Поиск в глубину (DFS): Реализуйте функцию dfs для обхода графа. Обновите ранги узлов и определите минимальный ранг для текущего узла. Проверьте, можно ли удалить текущее соединение, и обновите минимальный ранг. 3⃣Поиск критических соединений: После завершения обхода DFS преобразуйте оставшиеся соединения в список и верните его. 😎 Решение:
class Solution {
public:
    vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) {
        formGraph(n, connections);
        dfs(0, 0);
        
        vector<vector<int>> result;
        for (auto& conn : connDict) {
            result.push_back({conn.first.first, conn.first.second});
        }
        return result;
    }

private:
    unordered_map<int, vector<int>> graph;
    unordered_map<int, int> rank;
    map<pair<int, int>, bool> connDict;
    
    void formGraph(int n, vector<vector<int>>& connections) {
        for (int i = 0; i < n; ++i) {
            graph[i] = vector<int>();
            rank[i] = -1;
        }
        for (auto& edge : connections) {
            int u = edge[0], v = edge[1];
            graph[u].push_back(v);
            graph[v].push_back(u);
            connDict[{min(u, v), max(u, v)}] = true;
        }
    }
    
    int dfs(int node, int discoveryRank) {
        if (rank[node] != -1) {
            return rank[node];
        }
        
        rank[node] = discoveryRank;
        int minRank = discoveryRank + 1;
        
        for (int neighbor : graph[node]) {
            if (rank[neighbor] != -1 && rank[neighbor] == discoveryRank - 1) {
                continue;
            }
            
            int recursiveRank = dfs(neighbor, discoveryRank + 1);
            
            if (recursiveRank <= discoveryRank) {
                connDict.erase({min(node, neighbor), max(node, neighbor)});
            }
            
            minRank = min(minRank, recursiveRank);
        }
        
        return minRank;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 650. 2 Keys Keyboard Сложность: medium На экране блокнота есть только один символ 'A'. Для каждого шага можно выполнить одну из двух операций над этим блокнотом: Copy All: скопировать все символы, присутствующие на экране (частичное копирование не допускается). Paste: Вы можете вставить символы, которые были скопированы в прошлый раз. Учитывая целое число n, верните минимальное количество операций, чтобы символ 'A' появился на экране ровно n раз. Пример:
Input: n = 3
Output: 3
👨‍💻 Алгоритм: 1⃣Используйте динамическое программирование для отслеживания минимального количества операций, необходимых для достижения определенного количества 'A' на экране. 2⃣Итерируйтесь от 1 до n, проверяя все возможные делители текущего числа и обновляя минимальное количество операций для каждого числа. 3⃣Возвращайте значение из таблицы динамического программирования для n. 😎 Решение:
int minSteps(int n) {
    if (n == 1) return 0;
    vector<int> dp(n + 1, 0);
    for (int i = 2; i <= n; ++i) {
        dp[i] = i;
        for (int j = 1; j <= i / 2; ++j) {
            if (i % j == 0) {
                dp[i] = min(dp[i], dp[j] + i / j);
            }
        }
    }
    return dp[n];
}
Ставь 👍 и забирай 📚 Базу знаний

Задача: 257. Binary Tree Paths Сложность: easy Дано бинарное дерево. Нужно вернуть все возможные пути от корня до листьев, гд
Задача: 257. Binary Tree Paths Сложность: easy Дано бинарное дерево. Нужно вернуть все возможные пути от корня до листьев, где путь представлен как строка вида "1->2->5". Пример:
Input: root = [1,2,3,null,5]
Output: ["1->2->5","1->3"]
👨‍💻 Алгоритм: 1⃣Рекурсивный обход дерева Если текущий узел не nullptr, добавляем его значение к строке path. 2⃣Проверка на лист Если это лист (нет ни левого, ни правого потомка), добавляем текущий путь в список paths. 3⃣Обход дочерних узлов Если узел не лист, продолжаем обход влево и вправо, дописывая "->" в строку пути. 😎 Решение:
class Solution {
public:
    void construct_paths(TreeNode* root, string path, vector<string>& paths) {
        if (root) {
            path += to_string(root->val);
            if (!root->left && !root->right) {
                paths.push_back(path);
            } else {
                path += "->";
                construct_paths(root->left, path, paths);
                construct_paths(root->right, path, paths);
            }
        }
    }

    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> paths;
        construct_paths(root, "", paths);
        return paths;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 729. My Calendar I Сложность: medium Вы создаете программу для использования в качестве календаря. Мы можем добавить новое событие, если его добавление не приведет к двойному бронированию. Двойное бронирование происходит, когда два события имеют некоторое непустое пересечение (т.е, Событие можно представить в виде пары целых чисел start и end, которая представляет собой бронирование на полуоткрытом интервале [start, end), диапазоне вещественных чисел x таких, что start <= x < end. Реализация класса MyCalendar: MyCalendar() Инициализирует объект календаря. boolean book(int start, int end) Возвращает true, если событие может быть успешно добавлено в календарь, не вызывая двойного бронирования. В противном случае возвращается false и событие не добавляется в календарь. Пример:
Input
["MyCalendar", "book", "book", "book"]
[[], [10, 20], [15, 25], [20, 30]]
Output
[null, true, false, true]
👨‍💻 Алгоритм: 1⃣Создайте класс MyCalendar с инициализатором для хранения списка событий. 2⃣Реализуйте метод book(int start, int end) для проверки пересечения нового события с уже существующими событиями. 3⃣Если новое событие не пересекается с существующими событиями, добавьте его в список событий и верните true. В противном случае верните false. 😎 Решение:
class MyCalendar {
public:
    MyCalendar() {}

    bool book(int start, int end) {
        for (const auto& event : events) {
            if (start < event[1] && end > event[0]) {
                return false;
            }
        }
        events.push_back({start, end});
        return true;
    }

private:
    vector<pair<int, int>> events;
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 946. Validate Stack Sequences Сложность: medium Учитывая, что два целочисленных массива pushed и popped имеют разные значения, верните true, если это могло быть результатом последовательности операций push и pop на изначально пустом стеке, или false в противном случае. Пример:
Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
Output: true
👨‍💻 Алгоритм: 1⃣Инициализировать пустой стек. Использовать указатель j для отслеживания текущей позиции в массиве popped. 2⃣Пройти по каждому элементу в массиве pushed: Добавить элемент в стек. Проверить верхний элемент стека: Если он совпадает с текущим элементом в popped, удалить элемент из стека и увеличить указатель j. 3⃣В конце вернуть true, если указатель j достиг конца массива popped, иначе вернуть false. 😎 Решение:
class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        stack<int> st;
        int j = 0;
        for (int x : pushed) {
            st.push(x);
            while (!st.empty() && j < popped.size() && st.top() == popped[j]) {
                st.pop();
                j++;
            }
        }
        return j == popped.size();
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Зарплата 207.000р у Middle-разработчика в Яндекс «В день уходит несколько часов на созвоны, в остальное время закрываю задачк
Зарплата 207.000р у Middle-разработчика в Яндекс «В день уходит несколько часов на созвоны, в остальное время закрываю задачки из спринта, редко перерабатываю. У компании топовый офис, но с коллективом как-то не заладилось. Радуюсь классному ДМС и стабильной зарплате» - middle разработчик из Яндекса. Бигтех по-русски - канал с реальными зарплатами и историями IT-специалистов российского БигТеха. Там уже опубликованы рассказы программистов Альфа-банка, Сбера и Тинькофф 🤯 Читайте: @bigtech_russia

Задача: 1091. Shortest Path in Binary Matrix Сложность: medium Дан бинарный матричный массив grid размером n x n. Верните длину самого короткого чистого пути в матрице. Если чистого пути не существует, верните -1. Чистый путь в бинарной матрице — это путь из верхнего левого угла (т.е. (0, 0)) в нижний правый угол (т.е. (n - 1, n - 1)), такой что: Все посещенные клетки пути равны 0. Все соседние клетки пути соединены по 8 направлениям (т.е. они различны и имеют общую сторону или угол). Длина чистого пути — это количество посещенных клеток этого пути. Пример:
Input: grid = [[0,1],[1,0]]
Output: 2
👨‍💻 Алгоритм: 1⃣Проверить, что начальная и конечная клетки открыты (равны 0). Если нет, вернуть -1. 2⃣Выполнить поиск в ширину (BFS) из начальной клетки, добавляя в очередь соседние клетки, если они открыты и еще не посещены. Обновлять длину пути для каждой клетки. 3⃣Если достигнута конечная клетка, вернуть длину пути. Если очередь пуста и конечная клетка не достигнута, вернуть -1. 😎 Решение:
#include <vector>
#include <queue>
using namespace std;

class Solution {
public:
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        if (grid[0][0] != 0 || grid[grid.size() - 1][grid[0].size() - 1] != 0) {
            return -1;
        }

        vector<vector<int>> directions = {
            {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}
        };

        queue<pair<int, int>> q;
        q.push({0, 0});
        grid[0][0] = 1;

        while (!q.empty()) {
            auto [row, col] = q.front(); q.pop();
            int distance = grid[row][col];
            if (row == grid.size() - 1 && col == grid[0].size() - 1) {
                return distance;
            }
            for (auto& direction : directions) {
                int newRow = row + direction[0];
                int newCol = col + direction[1];
                if (newRow >= 0 && newCol >= 0 && newRow < grid.size() && newCol < grid[0].size() && grid[newRow][newCol] == 0) {
                    q.push({newRow, newCol});
                    grid[newRow][newCol] = distance + 1;
                }
            }
        }
        return -1;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Задача: 986. Interval List Intersections Сложность: medium Вам даны два списка закрытых интервалов, firstList и secondList, где firstList[i] = [starti, endi] и secondList[j] = [startj, endj]. Каждый список интервалов является попарно непересекающимся и отсортированным. Верните пересечение этих двух списков интервалов. Закрытый интервал [a, b] (где a <= b) обозначает множество действительных чисел x с a <= x <= b. Пересечение двух закрытых интервалов - это множество действительных чисел, которые либо пусты, либо представлены как закрытый интервал. Например, пересечение [1, 3] и [2, 4] равно [2, 3]. Пример:
Input: firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
👨‍💻 Алгоритм: 1⃣Инициализация указателей: Завести два указателя i и j, указывающие на начало firstList и secondList соответственно. 2⃣Поиск пересечений: Пока оба указателя находятся в пределах своих списков, выполнить следующие действия: Найти максимальное начало и минимальный конец текущих интервалов. Если начало меньше или равно концу, добавить пересечение в результат. Сдвинуть указатель списка, у которого текущий интервал заканчивается раньше. 3⃣Возврат результата: Вернуть список пересечений. 😎 Решение:
class Solution {
public:
    vector<vector<int>> intervalIntersection(vector<vector<int>>& firstList, vector<vector<int>>& secondList) {
        vector<vector<int>> result;
        int i = 0, j = 0;
        
        while (i < firstList.size() && j < secondList.size()) {
            int start = max(firstList[i][0], secondList[j][0]);
            int end = min(firstList[i][1], secondList[j][1]);
            
            if (start <= end) {
                result.push_back({start, end});
            }
            
            if (firstList[i][1] < secondList[j][1]) {
                i++;
            } else {
                j++;
            }
        }
        
        return result;
    }
};
Ставь 👍 и забирай 📚 Базу знаний

Telegram опубликовал список 8 самых быстрорастущих каналов для программистов: Only Python — Подборки приёмов и фич, о которых
Telegram опубликовал список 8 самых быстрорастущих каналов для программистов: Only Python — Подборки приёмов и фич, о которых не рассказывают в курсах. Only Tech — Главные тренды и инсайды из мира технологий, маркетинга и интернет-культуры. Only Hack — Реальные кейсы кибератак, инструменты и методы защиты, которые используют хакеры. Only GitHub — Репозитории, которые решают реальные задачи. Скрипты, фреймворки и готовые решения Only IT — Без мнений и слухов — только факты и важные IT-события. Only Apple — Новые апдейты, утечки и фишки, которые Apple ещё не показала. Only GPT — Промпты, хаки и свежие инструменты, о которых молчат даже AI-каналы. Only Memes — Если ты когда-нибудь деплоил в пятницу вечером — ты поймешь Подписывайтесь и прокачивайте свои скиллы.

📺 База 1000+ реальных собеседований На программиста, тестировщика, аналитика, проджекта и другие IT профы. Есть собесы от ведущих компаний: Сбер, Яндекс, ВТБ, Тинькофф, Озон, Wildberries и т.д. 🎯 Переходи по ссылке и присоединяйся к базе, чтобы прокачать свои шансы на успешное трудоустройство!

Задача: 990. Satisfiability of Equality Equations Сложность: medium Дан массив строк equations, представляющий отношения между переменными, где каждая строка equations[i] имеет длину 4 и принимает одну из двух форм: "xi==yi" или "xi!=yi". Здесь xi и yi - это строчные буквы (не обязательно разные), представляющие имена переменных из одной буквы. Верните true, если возможно назначить целые числа именам переменных таким образом, чтобы удовлетворить всем заданным уравнениям, или false в противном случае. Пример:
Input: equations = ["b==a","a==b"]
Output: true
Explanation: We could assign a = 1 and b = 1 to satisfy both equations.
👨‍💻 Алгоритм: 1⃣Создание графа для уравнений "==": Создайте структуру данных для объединения (Union-Find) для обработки уравнений равенства. Пройдите через массив equations и для каждого уравнения типа "xi==yi" объедините соответствующие переменные. 2⃣Проверка уравнений "!=": Пройдите через массив equations и для каждого уравнения типа "xi!=yi" проверьте, принадлежат ли переменные к одной и той же группе в структуре объединения. Если принадлежат, верните false. 3⃣Возврат результата: Если после проверки всех уравнений "xi!=yi" не было обнаружено противоречий, верните true. 😎 Решение:
class Solution {
public:
    bool equationsPossible(vector<string>& equations) {
        UnionFind uf(26);
        
        for (const auto& eq : equations) {
            if (eq[1] == '=') {
                int x = eq[0] - 'a';
                int y = eq[3] - 'a';
                uf.unionSet(x, y);
            }
        }
        
        for (const auto& eq : equations) {
            if (eq[1] == '!') {
                int x = eq[0] - 'a';
                int y = eq[3] - 'a';
                if (uf.connected(x, y)) {
                    return false;
                }
            }
        }
        
        return true;
    }
    
private:
    class UnionFind {
    public:
        UnionFind(int n) : parent(n) {
            iota(parent.begin(), parent.end(), 0);
        }
        
        int find(int x) {
            if (parent[x] != x) {
                parent[x] = find(parent[x]);
            }
            return parent[x];
        }
        
        void unionSet(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);
            if (rootX != rootY) {
                parent[rootX] = rootY;
            }
        }
        
        bool connected(int x, int y) {
            return find(x) == find(y);
        }
        
    private:
        vector<int> parent;
    };
};
Ставь 👍 и забирай 📚 Базу знаний