Leetcode 第 364 场周赛题解

【周赛364-单调栈】美丽塔 II-力扣 2866 💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨。 阅读详情

Leetcode 第 364 场周赛题解

题目1:2864. 最大二进制奇数

思路

贪心。

要得到最大二进制奇数,则高位尽可能放 1,为了是奇数,最后一位必须是 1。

设原字符串的长度为 n,统计原字符串中 ‘1’ 的个数,记为 count_one。

新字符串 = count_one - 1 个 ‘1’ + n - count_one 个 ‘0’ + ‘1’。

代码

/*
 * @lc app=leetcode.cn id=2864 lang=cpp
 *
 * [2864] 最大二进制奇数
 */

// @lc code=start
class Solution
{
public:
    string maximumOddBinaryNumber(string s)
    {
        int n = s.size(), count_one = 0;
        for (char &c : s)
            if (c == '1')
                count_one++;
        string ans;
        for (int i = 0; i < count_one - 1; i++)
            ans += '1';
        for (int i = 0; i < n - count_one; i++)
            ans += '0';
        ans += '1';
        return ans;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n),其中 n 是字符串的长度。

空间复杂度:O(1)。

题目2:美丽塔 I

思路

枚举峰值的位置,向左、向右求高度和,更新高度和的最大值。

代码

/*
 * @lc app=leetcode.cn id=2865 lang=cpp
 *
 * [2865] 美丽塔 I
 */

// @lc code=start
class Solution
{
public:
    long long maximumSumOfHeights(vector<int> &maxHeights)
    {
        int n = maxHeights.size();
        long long max_sum = 0;
        // 枚举峰值的位置
        for (int i = 0; i < n; i++)
        {
            long long cur_sum = maxHeights[i];
            // 向左求和
            int left_height = maxHeights[i];
            for (int j = i - 1; j >= 0; j--)
            {
                left_height = min(left_height, maxHeights[j]);
                cur_sum += left_height;
            }
            // 向右求和
            int right_height = maxHeights[i];
            for (int j = i + 1; j < n; j++)
            {
                right_height = min(right_height, maxHeights[j]);
                cur_sum += right_height;
            }
            // 更新答案
            max_sum = max(max_sum, cur_sum);
        }
        return max_sum;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n2),其中 n 是数组 maxHeights 的长度。

空间复杂度:O(1)。

题目3:美丽塔 II

思路

思考优化:

以示例 [6,5,3,9,2,7] 为例,我们观察以 3 和 9 作为山顶的两个方案:

  • 以 3 作为山顶:3 3 |3 3| 2 2
  • 以 9 作为山顶:3 3 |3 9| 2 2

可以发现:以 3 作为山顶的左侧与以 9 为山顶的右侧在两个方案之间是可以复用的,至此发现解决方法:我们可以分别预处理出以每个节点作为山顶的前缀和后缀的和:

  • prev[i] 表示以 maxHeights[i] 作为山顶时左侧段的前缀和;
  • suffix[i] 表示以 maxHeights[i] 作为山顶时右侧段的后缀和。

那么,最佳方案就是 prev[i]+suffix[i]−maxHeight[i] 的最大值。 现在,最后的问题是如何以均摊 O(1) 的时间复杂度计算出每个元素前后缀的和?

继续以示例 [6,5,3,9,2,7] 为例:

  • 以 6 为山顶,前缀为 [6]
  • 以 5 为山顶,需要保证左侧元素不大于 5,因此找到 666 并修改为 555,前缀为 [5,5]
  • 以 3 为山顶,需要保证左侧元素不大于 3,因此找到两个 555 并修改为 333,前缀为 [3,3,3]
  • 以 9 为山顶,需要保证左侧元素不大于 9,不需要修改,前缀为 [3,3,3,9]
  • 以 2 为山顶,需要保证左侧元素不大于 2,修改后为 [2,2,2,2,2]
  • 以 7 为山顶,需要保证左侧元素不大于 7,不需要修改,前缀为 [2,2,2,2,2,7]

观察以上步骤,问题的关键在于修改操作:由于数组是递增的,因此修改的步骤就是在「寻找小于等于当前元素 x 的上一个元素」,再将中间的元素削减为 x。「寻找上一个更小元素」,这是单调栈的典型场景。

代码

/*
 * @lc app=leetcode.cn id=2866 lang=cpp
 *
 * [2866] 美丽塔 II
 */

// @lc code=start
class Solution
{
public:
    long long maximumSumOfHeights(vector<int> &maxHeights)
    {
        int n = maxHeights.size();
        vector<long long> suffix(n + 1, 0);
        vector<long long> prev(n + 1, 0);
        stack<int> s;
        // 单调栈求前缀
        for (int i = 0; i < n; i++)
        {
            // 弹出栈顶
            while (!s.empty() && maxHeights[s.top()] > maxHeights[i])
                s.pop();
            int j = s.empty() ? -1 : s.top();
            prev[i + 1] = prev[j + 1] + (long long)(i - j) * maxHeights[i];
            s.push(i);
        }
        // 清空栈
        while (!s.empty())
            s.pop();
        // 单调栈求后缀
        for (int i = n - 1; i >= 0; i--)
        {
            // 弹出栈顶
            while (!s.empty() && maxHeights[s.top()] > maxHeights[i])
                s.pop();
            int j = s.empty() ? n : s.top();
            suffix[i] = suffix[j] + (long long)(j - i) * maxHeights[i];
            s.push(i);
        }
        // 合并
        long long max_sum = 0;
        for (int i = 0; i < n; i++)
            max_sum = max(max_sum, prev[i + 1] + suffix[i] - maxHeights[i]);
        return max_sum;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n),其中 n 是数组 maxHeights 的长度。在一侧的计算中,每个元素最多如何和出栈 1 次。

空间复杂度:O(n),其中 n 是数组 maxHeights 的长度。

题目4:统计树中的合法路径数目

超出能力范围。

思路

经典的树型 DP 模型。维护以下值:

  • fu 表示以节点 u 为起点,以 u 的子树中某个节点为终点的路径中,所有点编号都是合数的路径有几条。
  • gu 表示以节点 u 为起点,以 u 的子树中某个节点为终点的路径中,有一个点的编号为质数的路径有几条。

answer += f[u] * g[v] + f[v] * g[u]。

题解:

https://leetcode.cn/problems/count-valid-paths-in-a-tree/solutions/2456568/shu-dp-by-tsreaper-of6v/

【图解】O(n) 线性做法(Python/Java/C++/Go)

代码

/*
 * @lc app=leetcode.cn id=2867 lang=cpp
 *
 * [2867] 统计树中的合法路径数目
 */

// @lc code=start

// 树型 DP

class Solution
{
private:
    #define MAXN (int)1e5
    bool inited = false;
    bool flag[MAXN + 10];

    // 筛法预处理 1e5 以内的质数
    void init()
    {
        if (inited)
            return;
        inited = true;

        memset(flag, 0, sizeof(flag));
        flag[0] = flag[1] = true;
        for (int i = 2; i * i <= MAXN; i++)
            if (!flag[i])
                for (int j = i << 1; j <= MAXN; j += i)
                    flag[j] = true;
    }

public:
    long long countPaths(int n, vector<vector<int>> &edges)
    {
        init();

        vector<int> e[n + 1];
        for (auto &edge : edges)
        {
            e[edge[0]].push_back(edge[1]);
            e[edge[1]].push_back(edge[0]);
        }

        long long ans = 0;
        int f[n + 1], g[n + 1];
        // 树 dp
        function<void(int, int)> dfs = [&](int sn, int fa)
        {
            if (flag[sn])
                f[sn] = 1, g[sn] = 0;
            else
                f[sn] = 0, g[sn] = 1;
            for (int fn : e[sn])
                if (fn != fa)
                {
                    dfs(fn, sn);
                    // 路径上深度最低的节点为 sn,这样的合法路径有几条
                    ans += f[sn] * g[fn] + g[sn] * f[fn];
                    // 更新以 sn 为起点,且走到子树里的路径数量
                    if (flag[sn])
                    {
                        f[sn] += f[fn];
                        g[sn] += g[fn];
                    }
                    else
                    {
                        g[sn] += f[fn];
                    }
                }
        };
        dfs(1, 0);
        return ans;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n),其中 n 是数组 edges 的长度。

空间复杂度:O(n),其中 n 是数组 edges 的长度。

数字IC后端时钟树综合实战:OCC电路优化与时钟树平衡策略 本文深入探讨了数字IC后端设计中时钟树综合的关键挑战,重点分析了OCC电路时钟树优化的必要性。通过实战案例,详细阐述了如何通过手动干预、时钟分组与分段长树等策略,避免工具自动平衡导致的时序违例和资源浪费,从而有效实现时钟树平衡并提升设计质量。 阅读详情

相关推荐

旋转变压器软件解码simulink仿真

旋转变压器软件解码simulink仿真、电机转速位置测量

qq_31446727的博客 2584

leetcode 第 364 场周赛

比如求当前值到后面的满足要求的值。枚举到当前值是小于栈顶元素的,那么我们肯定需要把栈顶元素拿出来,然后替换成当前值,详细的解释可以看灵神题解有很详细的解释,这里栈的功能就是优化的,帮助我们求出满足要求的前缀和后缀和。所以我们可以只枚举质数节点作为根节点的合法路径数目和,假设x为质数根节点,它有三个子树,分别2,3,4,2表示这个子树能枚举到的所有非质数个数,那么2*3;核心思想:枚举每个值作为峰值,然后从当前值,往前进行遍历不断取最小的,同理往后遍历,也不断取最小的,时间复杂度为O(n**2)。

saonantabusao的博客 335

51单片机定时器的原理、应用与编程实现

本文系统介绍了51单片机定时器的基本原理与应用。首先阐述了定时器的工作原理,包括定时模式和计数模式的区别。然后详细讲解了定时器的四种工作模式(方式0-方式3)及其适用场景,并分析了相关寄存器(TMOD、TCON、THx/TLx)的功能设置。文章还给出了定时器编程的具体步骤,包括初始化、计数初值计算和示例代码。最后通过LED闪烁、PWM波形产生、脉冲计数等实际应用案例,展示了定时器的多样化应用。掌握这些知识对嵌入式系统开发具有重要意义。

2501_91227323的博客 1524

LeetCode 周赛上分之旅 #47 前后缀分解结合单调栈的贡献问题

⭐️学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。本文是 LeetCode 上分之旅系列的第 47 篇文章,往期回顾请移步到文章末尾~

pengxurui的博客 394

CameraLink接口详解:从引脚定义到信号传输

本文详细解析了CameraLink接口的物理连接与信号传输机制。从MDR26连接器的引脚定义与镜像关系入手,深入讲解了BASE与MEDIUM模式下的信号映射、LVDS差分传输原理,并强调了屏蔽层处理与端接电阻等关键硬件设计细节。文章结合实战经验,提供了常见图像传输问题的排查思路,是工业视觉领域高速图像传输的实用指南。

weixin_28318011的博客 889

【STM32G474实战】RS485通信的DMA优化策略与性能对比

本文深入探讨了在STM32G474微控制器上优化RS485通信的DMA策略。通过对比轮询、中断和DMA三种数据传输方式的代码实现与性能,揭示了DMA在解放CPU、降低占用率方面的巨大优势。文章提供了详细的DMA配置指南、高级应用技巧(如结合空闲中断)以及一个高可靠通信框架的实战思路,旨在帮助开发者构建高效、实时的工业控制系统。

weixin_29268331的博客 304

【LeetCode】力扣364.周赛题解

将一个字符串中原有的一重新排列组合,将1尽可能的放到高位.最后留一位放在低位即可.

qq_62839589的博客 827

Ubuntu新手必看:3种方法快速查看和编辑JSON文件(附jq安装指南)

本文为Ubuntu新手详细介绍了三种查看和编辑JSON文件的核心方法:命令行利器jq、灵活脚本Python以及直观的图形化编辑器(如VS Code)。文章重点解析了jq的安装与核心用法,并对比了各方案的优缺点,帮助用户根据快速查询、复杂处理或直观编辑等不同场景,选择最合适的工具,从而高效处理JSON数据。

weixin_29229989的博客 418

动态规划(Dynamic Programming)详解:从入门到 LeetCode Hot 100

将一个复杂问题拆分成多个规模更小的子问题,通过保存子问题的计算结果,避免重复计算,最终得到原问题的答案。先看一个经典问题。dp[i] = 以第 i 个元素结尾的最优结果例如最长递增子序列。最长递增子序列不一定以最后一个元素结尾,因此必须遍历整个数组取最大值。dp[i] = 前 i 个元素的最优结果这种情况下,最终答案通常就是dp[n]。关键在于理解 dp 数组的定义。动态规划的核心并不是背诵某个固定模板,而是建立正确的状态定义,并通过状态转移方程解决问题。dp[i] 或 dp[i][j] 表示什么?

zengjiajun2006的博客 889

Dofbot机械臂从零部署笔记(1)——ROS之创建URDF模型、配置Moveit和MotionPlanning

Dofbot机械臂从零部署笔记(1)——ROS之创建URDF模型、配置Moveit和MotionPlanning

takedachia的博客 8700

【AUTOSAR-DEM】-2.4-APP SWC如何读取MIL灯状态以及配置MIL灯

该篇博文将告诉您: MIL(Malfunction Indicator Lamp/Light)灯的点灯和灭灯过程; DEM模块如何配置MIL灯; APP SWC如何获取MIL灯状态。

「汽车电子助手」的博客 1712

Hash表:两数之和、字母异位词分组、最长连续序列 [力扣 Hot100]

三道高频哈希表应用题:两数之和(利用HashMap快速查找补数)、字母异位词分组(排序后作为键分组)、最长连续序列(通过HashSet去重并仅从序列起点扩展)。核心思想均为借助哈希结构优化查找效率,避免重复计算。同时提及双指针等其他解法思路,体现算法设计中“空间换时间”的典型策略。

2403_87560480的博客 227

影楼精修-肤色统一算法解析

本文介绍了影楼精修中肤色统一算法的实现方案,并以像素蛋糕软件为例进行详细分析。肤色统一旨在通过调整人像照片中皮肤区域的颜色,使其看起来更加均匀一致。像素蛋糕软件提供了AI肤色统一和传统肤色统一两种功能,分别适用于不同需求。传统肤色统一算法通过皮肤分割、人脸检测、亮度统一和颜色统一等步骤,实现了对皮肤区域的精细调整。文章还提供了亮度统一的核心代码,并对比了传统算法与AI算法的效果,指出AI算法在自然度和亮度矫正方面表现更优。整体而言,本文为影楼精修中的肤色统一提供了实用的技术参考。

Trent1985的专栏 2071

力扣73 矩阵置零

该解法通过标记含0的行和列来实现矩阵置零。遍历矩阵,用布尔数组记录有0的行和列;再遍历一次,若当前行或列被标记,则置为0。时间复杂度O(mn),空间复杂度O(m+n)。

Pniubi的博客 35

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

LeetCode 3105.最长的严格递增或递减子数组:一次遍历

LeetCode 3105.最长的严格递增或递减子数组:一次遍历

<font color="Pink">Tisfy的博客</font> 190

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

LeetCode Hot 100 二叉树专题(三):BST 二叉搜索树与右视图(Java)

本专题主线:三题(98 / 230 / 199)共用两把钥匙——BST 的中序序列严格递增,以及遍历中的"层"与"深度"标记。看懂这两点,三题共用一套模板。 结构约定:每题统一分三部分——①题目分析与解题思路(含易错点辨析);②常见解法(附代码)及讲解;③知识点总结。

2401_88612756的博客 717

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【双指针|LeetCode1089 复写零】巧用逆向思路,破解原地覆盖陷阱

LeetCode1089.复写零要求原地复写数组中的0,避免覆盖未读元素。正向遍历会因写入操作破坏后续数据,故不可行。正确解法为逆向双指针:先正向预处理确定目标末尾位置,再从后向前复写,遇0写两个0,非0则直接搬运。需特别处理0复写越界情况(仅保留一个0)。时间复杂度O(n),空间复杂度O(1),是原地数组操作的经典范例。

2602_95684935的博客 231

力扣240搜索二维矩阵(二分查找)

本文介绍在力扣240题“搜索二维矩阵II”中,对每一行独立使用二分查找的解法。通过遍历每行并调用二分查找函数判断目标值是否存在,若找到则返回true,否则最终返回false。该方法利用了每行有序的特性,时间复杂度为O(m log n),其中m为行数,n为列数。具体二分查找逻辑可参考作者主页中关于力扣35题“搜索插入位置”的实现。

Pniubi的博客 88

力扣35搜索插入位置(二分查找)

该题通过二分查找寻找插入位置。使用 mid = (left + right) >> 1 防止整数溢出,等价于 (left + right) / 2,但更安全。当 target <= nums[mid] 时,更新答案并继续向左查找;否则向右。最终返回最小的插入位置,时间复杂度 O(log n),空间复杂度 O(1)。

Pniubi的博客 195

LeetCode100 94. 二叉树的中序遍历

中序遍历(左根右)通过栈实现,模拟递归过程。从根开始,不断向左走并压栈,直到左子树为空;弹出栈顶节点访问(根),转向其右子树重复流程。样例:1→2→3,遍历顺序为1→3→2。时间复杂度O(n),空间复杂度O(h)。

Shaoxingzong的博客 164

动态规划入门 ( - 力扣509斐波那契数)

本文总结动态规划基础题型,以斐波那契数为例,系统讲解动归五部曲:定义dp数组含义、推导递推公式、初始化dp数组、确定遍历顺序、打印调试。强调理解核心思路比死记硬背更重要,通过简单入门题掌握通用解题框架,为后续背包、打家劫舍、子序列等问题奠定基础。

Pniubi的博客 170

力扣hot100-滑动窗口最大值

先提交了一版结果用二重循环超时了。我还奇怪不是【困难】吗?这里面因为要判断堆顶元素下标,所以用了pair,来同时存放元素和下标。然后我又学习了官方题解,大根堆的方法。学到了一个新的容器:大根堆。heap.top();// 查看最大的数,不删除。heap.pop();

m0_61483444的博客 235

Rust LeetCode334 算法题解

本文分析了 LeetCode 334 题“递增的三元子序列”的两种解法。暴力法(三重循环)时间复杂度为 O(n³),仅适用于小数据;最优解采用一次扫描贪心策略,维护 first(最小值)和 second(递增对第二元素的最小值),通过三个分支判断:若当前数大于 second,则存在三元递增子序列;否则更新 first 或 second。算法正确性基于不变式:first 始终为已遍历最小值,second 为可形成递增对的最小尾部。时间复杂度 O(n),空间复杂度 O(1),适用于大规模数据。

weixin_43379230的博客 251

LeetCode100+拓扑排序+多源BFS+矩阵置零

摘要(≤150字): 三题均考察算法优化与经典思想。矩阵置零通过利用首行首列作标记,实现O(1)空间原地操作;腐烂橘子问题用BFS模拟感染过程,结合新鲜橘子计数判断是否可全部腐烂;课程表问题通过拓扑排序检测有向图是否存在环,基于入度数组与邻接表判断课程依赖是否可行。三者分别体现标记法、广搜传播与图论拓扑的核心应用。

记录大学学习学习成长过程,欢迎各位一起交流 565

[ 力扣Hot100 ]:双指针

本文总结了力扣中四道经典双指针题:移动零(双指针交换非零元素)、盛最多水的容器(左右指针收缩求最大面积)、三数之和(排序+双指针去重)及接雨水(前后缀最大值计算)。通过双指针技巧,有效优化时间复杂度,提升代码效率,体现其在数组问题中的核心应用价值。

2403_87560480的博客 284

LeetCode 面试经典 150_位运算_只出现一次的数字 II(137_C++_中等)

LeetCode 面试经典 150_位运算_只出现一次的数字 II(137_C++_中等) 题目描述: 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。

huayimenghan的博客 135
上一篇: Leetcode 第 365 场周赛题解
下一篇: Leetcode 第 363 场周赛题解
UestcXiye
博客等级 码龄8年 9032粉丝 1306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值