LeetCode美团专场——第203场周赛题解
发布日期:2025-04-05 04:39:25 浏览次数:8 分类:精选文章

本文共 3039 字,大约阅读时间需要 10 分钟。

目录

T1. 5495. 圆形赛道上经过次数最多的扇区

直接暴力模拟即可,注意圆环有一个开闭区间的问题,还有最后的一个数会没有被计数上,要单独判断。

T2. 5496. 你可以获得的最大硬币数目

这一题先排序,然后找出每隔两个找出需要获得的硬币数量相加,贪心的想法。

T3. 5497. 查找大小为 M 的最新分组

这题找长度恰好为 1 的子数组其实可以借鉴一下这一题的思想:

T4. 5498. 石子游戏 V

石子问题没有搞过,看大佬的题解吧!!经典的DP问题啊


T1. 5495. 圆形赛道上经过次数最多的扇区

直接暴力模拟即可,注意圆环有一个开闭区间的问题,还有最后的一个数会没有被计数上,要单独判断。

你可以尝试如下方法:

  • 初始化一个长度为 n + 1 的数组 ans,所有元素初始化为 0。
  • 创建一个额外的数组 temp,长度为 n + 1,所有元素初始化为 0。
  • 0n - 1 遍历每个起始点 i
    • 计算扇区的结束点 ji + k,其中 kn 前缀加上开闭区间的处理。
    • 使用条件判断确保区间是左闭右开的。
  • 对于每个扇区 _i_j,增加对应的计数。
  • 最终在 ans 中找到经过次数最多的扇区。
  • 注意事项:

    • 开闭区间导致最后一个数被漏判,因此需要额外判断。
    • 确保遍历所有可能的扇区组合。

    T2. 5496. 你可以获得的最大硬币数目

    这一题先排序,然后找出每隔两个找出需要获得的硬币数量相加,贪心的思想。

    具体步骤如下:

  • 对硬币堆进行排序。
  • 通过贪心算法,每次尽可能拿到最大的硬币。
  • 特别注意,当硬币堆数量为 3 时,直接返回中间的硬币数。
  • 对于其他情况,遍历硬币堆,找到每隔两个的堆,累加硬币数量。
  • 最终返回总数。
  • 优化提示:

    • 排序后的数组确保每次选择硬币都是最优选择。
    • 记录累加的起始位置,避免重复计算。

    实现代码如下:

    sort(piles.begin(), piles.end());int ans = 0;if (piles.size() == 3) return piles[1];for (int i = piles.size() - 2; i > piles.size() / 3 - 1; i -= 2) {    ans += piles[i];}return ans;

    T3. 5497. 查找大小为 M 的最新分组

    这题找长度恰好为 1 的子数组其实可以借鉴一下这一题的思想:

    具体方法:

  • 使用滑动窗口法进行处理。
  • 维护一个窗口,窗口内的元素和不能超过 M。
  • 滑动窗口时,双向调整左指针和右指针,确保窗口内的和不超过 M。
  • 每次找到满足条件的子数组时,记录起始和结束位置。
  • 最终输出所有满足条件的子数组。
  • 优化思路:

    • 渐进式调整窗口,避免超出时间复杂度。
    • 使用双指针技巧,高效地解决边界问题。
    • 最后挑选长度为 1 的子数组,确保符合题意。

    实现代码如下:

    int findLatestStep(vector
    &arr, int m) { int n = arr.size(); if (n == m) return n; map
    mp; mp[0] = n; for (int i = n - 1; i >= 0; --i) { int x = arr[i] - 1; auto it = prev(mp.upper_bound(x)); int l = it->first, r = it->second; if (l < x) { if (x - l == m) return i; mp[l] = x; } if (r > x + 1) { if (r - x - 1 == m) return i; mp[x + 1] = r; } } return -1;}

    T4. 5498. 石子游戏 V

    石子问题没有搞过,看大佬的题解吧!!经典的DP问题啊

    作者提供的解决方案:

    int stoneGameV(int[] stoneValue) {    int n = stoneValue.length;    int[] sum = new int[n];    sum[0] = stoneValue[0];    for (int i = 1; i < n; i++) {        sum[i] = sum[i - 1] + stoneValue[i];    }    int[][] dp = new int[n][n];    for (int i = 0; i < n; i++) {        for (int j = 0; j + i < n; j++) {            int left = j;            int right = j + i;            int max = 0;            for (int mid = left; mid < right; mid++) {                int sumleft = getsum(sum, left, mid);                int sumright = getsum(sum, mid + 1, right);                if (sumleft < sumright) {                    max = Math.max(max, sumleft + dp[left][mid]);                } else if (sumleft > sumright) {                    max = Math.max(max, sumright + dp[mid + 1][right]);                } else {                    max = Math.max(max, sumleft + dp[left][mid]);                    max = Math.max(max, sumright + dp[mid + 1][right]);                }            }            dp[left][right] = max;        }    }    return dp[0][n - 1];}int getsum(int[] sum, int left, int right) {    if (left == 0) {        return sum[right];    }    return sum[right] - sum[left - 1];}

    最终收益:

    • 时间复杂度:O(n^3)
    • 空间复杂度:O(n^2)
    • 提供一步步的详细解释,确保每一步的可行性

    总结:-Dynamic Programming(动态规划)是一种强大的工具,适用于需要分治和递归关系的问题。

    上一篇:LeetCode蔚来专场——第208场周赛题解
    下一篇:Leetcode经典系列——LRU最近最少使用机制

    发表评论

    最新留言

    很好
    [***.229.124.182]2025年04月19日 13时57分07秒