news 2026/6/16 20:35:19

从零开始写算法——贪心篇2:买卖股票的最佳时间 + 划分字母区间

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零开始写算法——贪心篇2:买卖股票的最佳时间 + 划分字母区间

在算法中,贪心算法 (Greedy Algorithm)往往是一个让人又爱又恨的话题。爱它是因为代码通常很短,恨它是因为“当前最优选择会导致全局最优”这个逻辑有时候很难一眼看穿。

今天我们通过两道经典的 LeetCode 题目——121. 买卖股票的最佳时机763. 划分字母区间,来感受一下贪心算法如何在“一次遍历”中解决问题。

这两个题目虽然场景完全不同,但核心思想是通用的:维护一个关键的状态变量(最小值或最远边界),在遍历过程中不断更新这个状态,从而得到最终答案。


Part 1:买卖股票的最佳时机 —— 维护“历史最低点”

1. 题目核心

给定一个数组prices,它的第i个元素是一支给定股票第i天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

2. 贪心策略

我们要赚钱,核心逻辑非常简单:“低买高卖”。 但是我们不能穿越时空,我们只能在当前这一天决定:

  1. 如果在今天卖出,我能赚多少?(取决于之前的最低价是多少)。

  2. 今天是不是一个新的“历史最低点”?如果是,那以后如果想买,肯定按今天的价格买更划算。

所以,我们需要维护一个变量min_price,代表过去几天(包括今天)出现的最低股价

3. 代码实现 (C++)

你的代码中有一个非常有意思的注释,关于“先算利润还是先更新最小值”的讨论,这体现了很好的思考深度。

C++代码实现:

class Solution { public: int maxProfit(vector<int>& prices) { // 思路就是我们通过一次遍历,但是这个遍历中我们去维护最小值,以及更新答案 // min_price 初始化为第一天的价格 int ans = 0, min_price = prices[0]; for (int x : prices) { /* 这里有一个细节逻辑: 我们是先计算 ans = max(ans, x - min_price),再更新 min_price。 这意味着我们计算的是:【今天的价格 - 之前几天的最低价】。 如果你反过来,先更新 min_price,再算 ans, 那么计算的就是:【今天的价格 - 包括今天在内的历史最低价】。 如果今天就是最低价,利润算出来是 0,反正 ans 初始化也是 0, 所以这两种写法对最终结果 ans 没有影响。 */ ans = max(ans, x - min_price); min_price = min(min_price, x); } return ans; } };

4. 复杂度分析

  • 时间复杂度:O(N)

    • 我们只用了一个for循环遍历数组prices,每个元素只访问了一次。

  • 空间复杂度:O(1)

    • 我们只使用了ansmin_price两个整数变量,不需要额外的数组空间。


Part 2:划分字母区间 —— 维护“最远边界”

1. 题目核心

给你一个字符串s。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。 例如:ababcbacadefegdehijhklija出现在最前面,也出现在下标 8 的位置。那么第一个片段至少要切在下标 8 之后,否则a就跨越两个片段了。

2. 贪心策略

这道题的贪心逻辑在于:一旦由于某个字母(比如 'a')被迫扩大了区间,这个区间内的所有其他字母(比如 'b', 'c')也得被包进来。

我们可以把这个问题分解为两个步骤:

  1. 预处理:每个人都想知道自己“最后出现的位置”在哪里。我们可以先遍历一遍,记下每个字母最后一次出现的下标。

  2. 合并区间

    • 我们维护一个end指针,表示当前片段至少要延伸到的位置

    • 当我们遍历到一个字符c时,看看它的最后出现位置是不是比当前的end还远?如果是,为了包住这个c,我们的片段必须延长(end变大)。

    • 何时收网?当遍历下标i追上了end时,说明这一段里所有出现过的字母,它们的最后一次出现位置都在i之前(或就是i)。此刻我们可以安全地切一刀!

3. 代码实现 (C++)

这一段代码完美诠释了“二次遍历”的思想。

C++代码实现:

class Solution { // 思路: 同一个字母最多出现在一个片段中,意味这个区间要包含所有这个字母,所以需要对区间进行划分 // 先计算每个字母对应下标,然后划分出区间,然而区间内的其他字母也会有自己对应的区间,此时应该进行合并区间 // 也就是我们目标两次遍历,第一次预处理,第二次进行划分。 public: vector<int> partitionLabels(string s) { int n = s.size(); // last 数组用来充当哈希表,记录每个字符最后出现的下标 // 大小为 26,对应 'a'-'z' int last[26]; for (int i = 0; i < n; ++i) { last[s[i] - 'a'] = i; // 不断更新,最后留下的就是最后一次出现的下标 } vector<int> ans; int start = 0, end = 0; // 第二次遍历:根据最远边界进行切割 for (int i = 0; i < n; ++i) { // 贪心核心:end 必须能包住当前字符 s[i] 的最后出现位置 end = max(end, last[s[i] - 'a']); // 如果当前的遍历下标 i 追上了 end,说明当前片段可以结束了 if(end == i) { ans.push_back(end - start + 1); // 计算当前片段长度 start = i + 1; // 更新下一个片段的起点 } } return ans; } };

4. 复杂度分析

  • 时间复杂度:O(N)

    • 虽然有两个for循环,但它们是并列的,不是嵌套的。

    • 第一个循环遍历N次构建last数组。

    • 第二个循环遍历N次进行切割。

    • 总操作次数是2N,在渐进复杂度中依然是 O(N)。

  • 空间复杂度:O(1)

    • 虽然我们开辟了一个last数组,但它的大小固定为 26(字符集大小),不随字符串长度N变化。在算法分析中,常数大小的空间视为 O(1)。

    • (注:返回值的ans数组通常不计入算法的空间复杂度,因为它用于存储结果)。


总结

这两道题虽然外表不同,但本质上都是线性扫描 + 状态更新

  1. 买卖股票:我们在扫描中更新最小值 (min),一旦遇到高价就计算利润。

  2. 划分字母:我们在扫描中更新最远边界 (end),一旦到达边界就进行切割。

这种“走一步看一步”且只需一次(或两次)遍历的方法,正是贪心算法在处理线性数据结构时的强大之处。掌握这种思维,能让你在面试中快速写出 O(N) 的高效代码。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/14 0:19:42

导师又让重写?千笔AI,最强的降AI率工具

在AI技术快速发展的今天&#xff0c;越来越多的学生开始借助AI工具辅助论文写作&#xff0c;以提高效率和质量。然而&#xff0c;随着学术审查标准的不断提升&#xff0c;AI生成内容的痕迹愈发明显&#xff0c;查重系统对AIGC&#xff08;人工智能生成内容&#xff09;的识别也…

作者头像 李华
网站建设 2026/6/15 20:18:39

单片机毕设 基于单片机的红外热视仪(源码+硬件+论文)

文章目录 0 前言1 主要功能2 硬件设计3 核心软件设计4 实现效果5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己…

作者头像 李华
网站建设 2026/6/14 5:27:22

AI教材写作新突破!低查重方法让你的教材脱颖而出!

AI教材创作工具助力教材编写 谁都会经历编写教材的难题&#xff1f;面对一片空白的文档&#xff0c;常常不知道从何入手&#xff0c;想了半天却毫无头绪——应该先介绍概念&#xff0c;还是先给出案例&#xff1f;章节的划分是依据逻辑&#xff0c;还是依照课时&#xff1f;反…

作者头像 李华
网站建设 2026/6/15 13:03:54

【小程序毕设全套源码+文档】基于android的健身房管理系统的设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/15 5:54:16

交稿前一晚!AI论文网站 千笔ai写作 VS 学术猹,专科生首选

随着人工智能技术的迅猛迭代与普及&#xff0c;AI辅助写作工具已逐步渗透到高校学术写作场景中&#xff0c;成为专科生、本科生、研究生完成毕业论文不可或缺的辅助手段。越来越多面临毕业论文压力的学生&#xff0c;开始依赖各类AI工具简化写作流程、提升创作效率。但与此同时…

作者头像 李华
网站建设 2026/6/9 20:02:01

专科生也能用!万众偏爱的降AI率平台 —— 千笔·降AIGC助手

在AI技术迅速渗透学术写作领域的当下&#xff0c;越来越多的学生和研究者开始依赖AI工具来提升论文撰写效率。然而&#xff0c;随之而来的“AI率超标”问题也日益凸显——随着查重系统不断升级&#xff0c;AI生成内容的痕迹越来越容易被识别&#xff0c;稍有不慎就可能面临论文…

作者头像 李华