LeetCode 2024/5 每日一题 合集

2024-5-6 1463. 摘樱桃 II

代码实现

class Solution {
public:
    int cherryPickup(vector<vector<int>>& grid) {
        int n = size(grid), m = size(grid[0]);
        std::vector f(n, std::vector(m, std::vector(m, -1)));
        auto dfs = [&](auto &&self, int x, int ya, int yb) ->int {
            int& u = f[x][ya][yb];
            if (u != -1) return u;
            u = grid[x][ya] + (ya != yb ? grid[x][yb] : 0);
            for (int fa = ya - 1; fa <= ya + 1; ++fa) {
                for (int fb = yb - 1; fb <= yb + 1; ++fb) {
                    if (fa < m && fb < m && x + 1 < n && fa >= 0 && fb >= 0) {
                        u = std::max(u, self(self, x + 1, fa, fb) + grid[x][ya] + (ya != yb ? grid[x][yb] : 0));
                    }
                }
            }
            return u;
        };
        return dfs(dfs, 0, 0, m - 1);
    }
};

戳这里前往原题(╹▽╹)

2024-5-7 2079. 给植物浇水

代码实现

class Solution {
public:
    int wateringPlants(vector<int>& plants, int capacity) {
        int n = size(plants), ans = 0;
        for (int i = 0; i < n; ++i) {
            int j = i, s = capacity;
            while (j < n && s - plants[j] >= 0) {
                s -= plants[j++];
            }
            ans += j + j * (j != n);
            i = j - 1;
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-8 2105. 给植物浇水 II

代码实现

class Solution {
public:
    int minimumRefill(vector<int>& plants, int capacityA, int capacityB) {
        int n = size(plants);
        int l = 0, r = n - 1, ans = 0;
        int A = capacityA, B = capacityB;
        while (l <= r) {
            if (A >= plants[l]) {
                A -= plants[l++];
            } else {
                if (l == r && B >= plants[l]) {
                    break;   
                }
                A = capacityA - plants[l++];
                ans += 1;
            }
            if (l > r) break;
            if (B >= plants[r]) {
                B -= plants[r--];
            } else {
                B = capacityB - plants[r--];
                ans += 1;
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-9 2960. 统计已测试设备

代码实现

class Solution {
public:
    int countTestedDevices(vector<int>& b) {
        int n = size(b), ans = 0;
        for (int i = 0; i < n; ++i) {
            if (b[i] > 0) {
                for (int j = i + 1; j < n; ++j) {
                    b[j] -= 1;
                }
                ans += 1;
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-10 2391. 收集垃圾的最少总时间

代码实现

class Solution {
public:
    int garbageCollection(vector<string>& garbage, vector<int>& travel) {
        int n = size(garbage);
        std::vector<int> pre(n);
        for (int i = 1; i < n; ++i) {
            pre[i] = pre[i - 1] + travel[i - 1]; 
        }
        int ans = 0;
        for (auto x : "MPG") {
            int sum = 0, last = 0;
            for (int i = 0; i < n; ++i) {
                int cnt = std::count(garbage[i].begin(), garbage[i].end(), x);
                if (cnt > 0) last = i;
                sum += cnt;
            }
            ans += pre[last] + sum;
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-11 1553. 吃掉 N 个橘子的最少天数

代码实现

class Solution {
public:
    int minDays(int n) {
        std:queue<int> q;
        q.emplace(n);
        std::unordered_map<int, int> mp;
        while (size(q)) {
            auto u = q.front();
            q.pop();
            if (u == 0) return mp[u];
            int num = mp[u];
            if (u % 2 == 0) {
                if (!mp.count(u / 2)) {
                    q.emplace(u / 2);
                    mp[u / 2] = num + 1;
                }
            }
            if (u % 3 == 0) {
                if (!mp.count(u - 2 * (u / 3))) {
                    q.emplace(u - 2 * (u / 3));
                    mp[u - 2 * (u / 3)] = num + 1;
                }
            }
            if (!mp.count(u - 1)) {
                mp[u - 1] = num + 1;
                q.emplace(u - 1);
            }
        }
        return mp[0];
    }
};

戳这里前往原题(╹▽╹)

2024-5-12 994. 腐烂的橘子

代码实现

class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        int n = size(grid), m = size(grid[0]);
        int ans = 0;
        auto work = [&](int x, int y) {
            for (auto [fx, fy] : {std::pair{x + 1, y}, {x - 1, y}, {x, y + 1}, {x, y - 1}}) {
                if (fx >= 0 && fy >= 0 && fx < n && fy < m && grid[fx][fy] == 1) {
                    grid[fx][fy] = 2;
                }
            }
        };
        while (true) {
            ans += 1;
            auto f = grid;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < m; ++j) if (f[i][j] == 2) {
                    work(i, j);
                }
            }
            if (grid == f) {
                break;
            }
        }
        int sum = 0;
        for (int i = 0; i < n; ++i) {
            sum += std::count(grid[i].begin(), grid[i].end(), 1);
        }
        return sum ? -1 : ans - 1;
    }
};

戳这里前往原题(╹▽╹)

2024-5-13 2244. 完成所有任务需要的最少轮数

代码实现

class Solution {
public:
    int minimumRounds(vector<int>& tasks) {
        std::map<int, int> mp;
        for (int i = 0; i < size(tasks); ++i) {
            mp[tasks[i]] += 1;
        }
        int ans = 0;
        for (auto [_, cnt] : mp) {
            if (cnt == 1) return -1;
            ans += cnt / 3 + (cnt % 3 != 0);
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-14 2589. 完成所有任务的最少时间

代码实现

class Solution {
public:
    int findMinimumTime(vector<vector<int>>& tasks) {
        std::sort(tasks.begin(), tasks.end(), 
            [&](std::vector<int>& x, std::vector<int>& y) {
                return x[1] < y[1];
            });
        std::vector<int> run(tasks.rbegin()[0][1] + 1);
        int ans = 0;
        for (auto task : tasks) {
            int dur = task[2];
            dur -= std::accumulate(run.begin() + task[0], run.begin() + task[1] + 1, 0LL);
            ans += std::max(dur, 0);
            for (int i = task[1]; i >= 0 && dur > 0; --i) if (run[i] == 0) {
               dur--;
               run[i] = 1; 
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-15 1953. 你可以工作的最大周数

代码实现

class Solution {
public:
    long long numberOfWeeks(vector<int>& milestones) {
        long long sum = std::accumulate(milestones.begin(), milestones.end(), 0LL);
        long long max = std::ranges::max(milestones);
        return max > sum - max + 1 ? (sum - max) * 2 + 1 : sum;
    }
};

戳这里前往原题(╹▽╹)

2024-5-16 826. 安排工作以达到最大收益

分析

每个工人最多只能安排一个工作,但是一个工作可以完成多次,则对工作收益进行排序,尽量让工人工作收益最高的工作,用multiset维护即可

代码实现

class Solution {
public:
    int maxProfitAssignment(vector<int>& difficulty, vector<int>& profit, vector<int>& worker) {
        int n = size(difficulty), m = size(worker);
        std::vector<int> ord(n);
        std::iota(ord.begin(), ord.end(), 0);
        std::sort(ord.begin(), ord.end(), 
            [&](int x, int y){
                return profit[x] > profit[y];
            });
        std::multiset<int> st = {worker.begin(), worker.end()};
        int ans = 0;
        for (int i = 0; i < n && size(st); ) {
            auto it = st.lower_bound(difficulty[ord[i]]);
            if (it == st.end()) {
                ++i;
            } else {
                st.erase(it);
                ans += profit[ord[i]];
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-17 2644. 找出可整除性得分最大的整数

代码实现

class Solution {
public:
    int maxDivScore(vector<int>& nums, vector<int>& divisors) {
        std::sort(divisors.begin(), divisors.end());
        int max = 0, ans = divisors[0];
        for (int i = 0; i < size(divisors); ++i) {
            int tot = 0;
            for (int j = 0; j < size(nums); ++j) {
                tot += nums[j] % divisors[i] == 0;
            }
            if (tot > max) {
                max = tot, ans = divisors[i];
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-18 1535. 找出数组游戏的赢家

代码实现

class Solution {
public:
    int getWinner(vector<int>& arr, int k) {
        int n = size(arr);
        int win = arr[0], cnt = 0;
        for (int i = 0; i < n; ++i) {
            int j = i + 1;
            while (j < n && arr[j] < win) {
                j += 1, cnt += 1;
            }
            if (cnt >= k) {
                return win;
            } else {
                win = arr[j], cnt = 1;
            }
            i = j - 1;
        }
        return std::ranges::max(arr);
    }
};

戳这里前往原题(╹▽╹)

2024-5-19 1542. 找出最长的超赞子字符串

分析

可以发现存在超赞子字符串的条件是,字符出现的次数为奇数的数量\(\leq 1\)。因此可以使用前缀和记录每个字符出现次数的奇偶,然后用map存下之前出现过的奇偶次数以便快速查询,最后扫一遍即可。

代码实现

class Solution {
public:
    int longestAwesome(string s) {
        int n = size(s);
        std::vector<std::array<int, 10>> pre(n + 1);
        std::map<int, int> mp{{0, 0}};
        int ans = 1;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < 10; ++j) {
                pre[i + 1][j] = pre[i][j] + (s[i] - '0' == j);
            }
            int u = 0;
            for (int j = 0; j < 10; ++j) {
                u += (pre[i + 1][j] & 1) << j;
            }
            for (int j = 0; j < 10; ++j) {
                int v = 1 << j;
                if (mp.count(u ^ v)) {
                    ans = std::max(ans, i - mp[u ^ v] + 1);
                }
            }
            if (!mp.count(u)) {
                mp[u] = i + 1;
            } 
            ans = std::max(ans, i - mp[u] + 1);
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-20 2769. 找出最大的可达成数字

代码实现

class Solution {
public:
    int theMaximumAchievableX(int num, int t) {
        return num + 2 * t;
    }
};

戳这里前往原题(╹▽╹)

2024-5-21 2225. 找出输掉零场或一场比赛的玩家

代码实现

class Solution {
public:
    vector<vector<int>> findWinners(vector<vector<int>>& matches) {
        std::map<int, int> lose;
        for (auto who : matches) {
            lose[who[1]] += 1, lose[who[0]] += 0;
        }
        std::vector<std::vector<int>> answer(2);
        for (auto [x, c] : lose) if (c <= 1) {
            answer[c].emplace_back(x);
        }
        return answer;
    }
};

戳这里前往原题(╹▽╹)

2024-5-22 2831. 找出最长等值子数组(双指针)

代码实现

class Solution {
public:
    int longestEqualSubarray(vector<int>& nums, int k) {
        int n = size(nums);
        std::vector<int> cnt(n + 1);
        int ans = 1, l = 0;
        for (int r = 0; r < n; ++r) {
            cnt[nums[r]]++;
            while (r - l + 1 - cnt[nums[l]] > k) {
                cnt[nums[l++]]--;
            }
            ans = std::max(ans, cnt[nums[l]]);
        }
        for (int i = l; i < n; ++i) {
            ans = std::max(ans, cnt[nums[i]]);
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-23 1673. 找出最具竞争力的子序列

分析

每次查询[i + 1, n - (k - ans.size())]的最小值,如果此时$i \leq $查询区间最小值则此时放置nums[i]最优,区间最小值用RMQ维护即可,发现查询区间为连续的,因此也可以尝试用multiset进行维护

代码实现

template<class T,
    class Cmp = std::less<T>>
struct RMQ {
    const Cmp cmp = Cmp();
    static constexpr unsigned B = 64;
    using u64 = unsigned long long;
    int n;
    std::vector<std::vector<T>> a;
    std::vector<T> pre, suf, ini;
    std::vector<u64> stk;
    RMQ() {}
    RMQ(const std::vector<T> &v) {
        init(v);
    }
    void init(const std::vector<T> &v) {
        n = v.size();
        pre = suf = ini = v;
        stk.resize(n);
        if (!n) return;
        const int M = (n - 1) / B + 1;
        const int lg = std::__lg(M);
        a.assign(lg + 1, std::vector<T>(M));
        for (int i = 0; i < M; ++i) {
            a[0][i] = v[i * B];
            for (int j = 1; j < B && i * B + j < n; ++j) {
                a[0][i] = std::min(a[0][i], v[i * B + j], cmp);
            }
        }
        for (int i = 1; i < n; ++i) {
            if (i % B) {
                pre[i] = std::min(pre[i], pre[i - 1], cmp);
            }
        }
        for (int i = n - 2; i >= 0; --i) {
            if (i % B != B - 1) {
                suf[i] = std::min(suf[i], suf[i + 1], cmp);
            }
        }
        for (int j = 0; j < lg; ++j) {
            for (int i = 0; i + (2 << j) <= M; ++i) {
                a[j + 1][i] = std::min(a[j][i], a[j][i + (1 << j)], cmp);
            }
        }
        for (int i = 0; i < M; ++i) {
            const int l = i * B;
            const int r = std::min(1U * n, l + B);
            u64 s = 0;
            for (int j = l; j < r; ++j) {
                while (s && cmp(v[j], v[std::__lg(s) + l])) {
                    s ^= 1ULL << std::__lg(s);
                }
                s |= 1ULL << (j - l);
                stk[j] = s;
            }
        }
    } 
    T operator()(int l, int r) { // [l, r)
        if (l / B != (r - 1) / B) {
            T ans = std::min(suf[l], pre[r - 1], cmp);
            l = l / B + 1;
            r = r / B;
            if (l < r) {
                int k = std::__lg(r - l);
                ans = std::min({ans, a[k][l], a[k][r - (1 << k)]}, cmp);
            }
            return ans;
        } else {
            int x = B * (l / B);
            return ini[__builtin_ctzll(stk[r - 1] >> (l - x)) + l];
        }
    }
};
class Solution {
public:
    vector<int> mostCompetitive(vector<int>& nums, int k) {
        int n = size(nums);
        RMQ rmq(nums);
        std::vector<int> ans;
        for (int i = 0; i < n && size(ans) < k; ++i) {
            if (nums[i] <= rmq(i, std::min<int>(n - (k - size(ans)) + 1, n))) {
                ans.emplace_back(nums[i]);
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-24 2831. 找出最长等值子数组

代码实现

class Solution {
public:
    int longestEqualSubarray(vector<int>& nums, int k) {
        int n = size(nums);
        std::vector<int> cnt(n + 1);
        int ans = 1, l = 0;
        for (int r = 0; r < n; ++r) {
            cnt[nums[r]]++;
            while (r - l + 1 - cnt[nums[l]] > k) {
                cnt[nums[l++]]--;
            }
            ans = std::max(ans, cnt[nums[l]]);
        }
        for (int i = l; i < n; ++i) {
            ans = std::max(ans, cnt[nums[i]]);
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-25 2903. 找出满足差值条件的下标 I

代码实现

class Solution {
public:
    vector<int> findIndices(vector<int>& nums, int indexDifference, int valueDifference) {
        int n = size(nums);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (abs(i - j) >= indexDifference && abs(nums[i] - nums[j]) >= valueDifference) {
                    return {i, j};
                }
            } 
        }
        return {-1, -1};
    }
};

戳这里前往原题(╹▽╹)

2024-5-26 1738. 找出第 K 大的异或坐标值

分析

即求前k大的前缀异或值

代码实现

class Solution {
public:
    int kthLargestValue(vector<vector<int>>& matrix, int k) {
        int n = size(matrix), m = size(matrix[0]);
        std::vector<int> ans;
        std::vector<std::vector<int>> pre(n + 1, std::vector<int>(m + 1)); 
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                pre[i][j] = pre[i - 1][j] ^ pre[i][j - 1] ^ pre[i - 1][j - 1] ^ matrix[i - 1][j - 1];
                ans.emplace_back(pre[i][j]);
            }
        }
        std::sort(ans.rbegin(), ans.rend());
        return ans[k - 1];
    }
};

戳这里前往原题(╹▽╹)

2024-5-27 2028. 找出缺失的观测数据

代码实现

class Solution {
public:
    vector<int> missingRolls(vector<int>& rolls, int mean, int n) {
        int m = size(rolls), sum = std::accumulate(rolls.begin(), rolls.end(), 0);
        int res = mean * (n + m) - sum;
        std::vector<int> ans(n, res / n);
        res -= res / n * n;
        for (int i = 0; i < n && res; res--, ++i) {
            ans[i] += 1;
        }
        if (std::accumulate(ans.begin(), ans.end(), 0) + sum != mean * (n + m) || ans[0] > 6 || ans.back() < 1) {
            return {};
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-28 2951. 找出峰值

代码实现

class Solution {
public:
    vector<int> findPeaks(vector<int>& mountain) {
        std::vector<int> ans;
        for (int i = 1; i < size(mountain) - 1; ++i) {
            if (mountain[i] > mountain[i - 1] && mountain[i] > mountain[i + 1]) {
                ans.emplace_back(i);
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-29 2981. 找出出现至少三次的最长特殊子字符串 I

分析

\(n \leq 50\),因此直接\(n ^ 2\)枚举所有字符串即可

代码实现

class Solution {
public:
    int maximumLength(string s) {
        std::unordered_map<std::string, int> mp;
        for (int i = 0; i < size(s); ++i) {
            std::string k;
            for (int j = i; j < size(s); ++j) {
                k += s[j];
                mp[k] += 1;
            }
        }
        int len = -1;
        for (auto [x, cnt] : mp) {
            if (cnt >= 3 && std::count(x.begin(), x.end(), x[0]) == size(x)) {
                len = std::max<int>(len, size(x));
            }
        }
        return len;
    }
};

戳这里前往原题(╹▽╹)

2024-5-30 2982. 找出出现至少三次的最长特殊子字符串 II

分析

发现\(n \leq 5e5\),显然不能暴力。观察题目可以发现最长特殊子字符串的的长度只与最长相同和次长相同字符串有关,因此直接统计所有字符的连续串长度,最后枚举一遍即可

代码实现

class Solution {
public:
    int maximumLength(string s) {
        std::vector<std::vector<int>> len(26);
        for (int i = 0; i < size(s); ++i) {
            int j = i + 1;
            while (j < size(s) && s[i] == s[j]) {
                j += 1;
            }
            len[s[i] - 'a'].emplace_back(j - i);
            i = j - 1;
        }
        int ans = -1;
        for (int i = 0; i < 26; ++i) { 
            std::sort(len[i].rbegin(), len[i].rend());
            if (size(len[i]) >= 3) {
                ans = std::max(ans, len[i][2]);
            }
            if (size(len[i]) >= 2 && len[i][1] + len[i][0] >= 3) {
                if (len[i][0] == len[i][1] + 1) {
                    ans = std::max(ans, len[i][1]);
                } else if (len[i][0] >= len[i][1] + 2) {
                    ans = std::max(ans, len[i][0] - 2);
                } else {
                    ans = std::max(ans, len[i][1] - 1);
                }
            }
            if (size(len[i]) >= 1 && len[i][0] >= 3) {
                ans = std::max(ans, len[i][0] - 2);
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

2024-5-31 2965. 找出缺失和重复的数字

代码实现

class Solution {
public:
    vector<int> findMissingAndRepeatedValues(vector<vector<int>>& grid) {
        int n = size(grid);
        std::vector<int> cnt(n * n + 1);
        std::vector<int> ans(2);
        for (int i = 0; i < size(grid); ++i) {
            for (int j = 0; j < size(grid[i]); ++j) {
                cnt[grid[i][j]] += 1;
            }
        }
        for (int i = 1; i <= n * n; ++i) {
            if (cnt[i] == 0) {
                ans[1] = i;
            }
            if (cnt[i] == 2) {
                ans[0] = i;
            }
        }
        return ans;
    }
};

戳这里前往原题(╹▽╹)

posted @ 2024-05-07 16:01  sleeeeeping  阅读(34)  评论(0)    收藏  举报