题解:学而思编程 最大回撤
【题目来源】
洛谷:最大回撤
【题目描述】
股票价格瞬息万变。在金融市场上,经常需要统计一只股票最大回撤。最大回撤是指投资者在某天买入,在之后的某天卖出,可能造成的最大亏损,它可以反应一只股票在历史上的最坏表现。
给定一个整数序列 \(a_1,a_2,a_3,⋯,a_n\),每个 \(a_i\) 表示某只股票的在某一天的价格,请计算这只股票的最大回撤。即寻找两个下标满足 \(1≤i≤j≤n\),且 \(a_i−a_j\) 最大。
【输入】
第一行,单个整数表示 \(n\);
第二行,\(n\) 个整数表示 \(a_1,a_2,a_3,⋯,a_n\)。
【输出】
一行一个整数,表示这只股票的最大回撤,如果价格一直上涨,输出 \(0\)。
【输入样例】
5
2 3 7 6 1
【输出样例】
6
【核心思想】
-
问题分析:给定长度为 \(n\) 的股票价格序列 \(a_1, a_2, \ldots, a_n\),求最大回撤,即 \(\max_{1 \leq i \leq j \leq n} (a_i - a_j)\)。若价格一直上涨则输出 \(0\)。这是一个前缀最大值 + 线性扫描问题,关键在于维护每个位置之前的历史最高价,然后计算当前价格与历史最高价的差值。
-
算法选择:
- 前缀最大值数组:
max_pre[i]表示前 \(i\) 个元素中的最大值,即 \(\max_{1 \leq t \leq i} a_t\) - 线性扫描求最大差值:遍历每个位置 \(i\),计算
max_pre[i] - a[i],取最大值
- 前缀最大值数组:
-
关键步骤:
- 初始化:读取 \(n\)(天数)和股票价格数组 \(a[1..n]\)
- 计算前缀最大值:
- \(max\_pre[0] = -\infty\)(极小值)
- 遍历 \(i\) 从 \(1\) 到 \(n\):
- \(max\_pre[i] = \max(max\_pre[i-1], a_i)\):前 \(i\) 天的历史最高价
- 计算最大回撤:
- \(ans = -\infty\)
- 遍历 \(i\) 从 \(1\) 到 \(n\):
- \(ans = \max(ans, max\_pre[i] - a_i)\):以第 \(i\) 天卖出,之前某天买入的最大亏损
- 处理非负约束:
- 若
ans < 0(价格一直上涨),输出 \(0\) - 否则输出
ans
- 若
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),两次线性遍历
- 空间复杂度:\(O(n)\),前缀最大值数组
max_pre[0..n](可优化至 \(O(1)\))
-
前缀最大值的核心思想:
- 最优子结构:最大回撤要求 \(i \leq j\),前缀最大值
max_pre[j]恰好是 \(a_j\) 之前(含)的最高价格,保证了买入时间不晚于卖出时间 - 分离变量:将 \(\max_{i \leq j} (a_i - a_j)\) 拆分为 \(\max_j (\max_{i \leq j} a_i - a_j) = \max_j (max\_pre[j] - a_j)\),将双重循环降为单重
- 贪心维护:
max_pre[i]只需与当前元素比较即可更新,无需重新遍历 - 空间优化:可用单个变量替代数组,实时维护当前前缀最大值,空间降至 \(O(1)\)
- 适用于"前缀最值 + 后续差值最优化"类问题,前缀预处理将 \(O(n^2)\) 暴力枚举优化为线性扫描
- 最优子结构:最大回撤要求 \(i \leq j\),前缀最大值
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 100005; // 定义最大数组长度
int n, a[N], max_pre[N], ans = -1e9; // 数组长度n,数组a,前缀最大值数组max_pre,答案ans
int main() // 主函数
{
cin >> n; // 输入数组长度
for (int i=1; i<=n; i++) // 读取数组元素
cin >> a[i]; // 输入第i个元素
max_pre[0] = -1e9; // 初始化前缀最大值为极小值
for (int i=1; i<=n; i++) // 计算前缀最大值
{
max_pre[i] = max(max_pre[i-1], a[i]); // 前i个元素的最大值
}
for (int i=1; i<=n; i++) // 计算最大差值
ans = max(ans, max_pre[i]-a[i]); // 更新最大差值
cout << ans << endl; // 输出答案
return 0; // 程序正常结束
}
【运行结果】
5
2 3 7 6 1
6
浙公网安备 33010602011771号