leetCode每日一题:按策略买卖股票的最佳时机
2026/6/10 21:11:44 网站建设 项目流程

下面我把LeetCode 3652:按策略买卖股票的最佳时机
完整做一遍:从建模 → 思路 → 算法 → 代码(含详细注释),一步一步来。
原题
给你两个整数数组 prices 和 strategy,其中:

prices[i] 表示第 i 天某股票的价格。 strategy[i] 表示第 i 天的交易策略,其中: -1 表示买入一单位股票。 0 表示持有股票。 1 表示卖出一单位股票。 同时给你一个 偶数 整数 k,你可以对 strategy 进行 最多一次 修改。一次修改包括: 选择 strategy 中恰好 k 个 连续 元素。 将前 k / 2 个元素设为 0(持有)。 将后 k / 2 个元素设为 1(卖出)。 利润 定义为所有天数中 strategy[i] * prices[i] 的 总和 。 返回你可以获得的 最大 可能利润。

注意: 没有预算或股票持有数量的限制,因此所有买入和卖出操作均可行,无需考虑过去的操作 做出这道题,并给出详细解释,分析,和注释

一、题意重述(用“数学 + 业务”语言)

给定:

  • prices[i]:第i天股价

  • strategy[i]:第i天策略

    • -1:买入 → 对利润贡献-prices[i]
    • 0:持有 → 贡献0
    • 1:卖出 → 贡献+prices[i]

原始利润

[
profit = \sum strategy[i] \times prices[i]
]


你可以做最多一次修改

修改规则:

  • 选一个长度为k连续子数组
  • k/2天 → 全部改成0
  • k/2天 → 全部改成1

⚠️k偶数


目标

修改 0 次或 1 次,使总利润最大


二、关键思维:问题本质是什么?

1️⃣ 原利润是固定的

baseProfit = Σ strategy[i] * prices[i]

我们只需要关心:

“一次修改,最多能额外增加多少利润”


2️⃣ 修改 = 对一段区间的“利润差值”

设修改区间是[l, r],长度k
其中:

  • [l, l + k/2 - 1]→ 改为0
  • [l + k/2, r]→ 改为1
原贡献
Σ strategy[i] * prices[i]
新贡献
前半段:0 后半段:+prices[i]
增量 = 新 - 原

三、把“增量”拆成两个部分

🔹 前半段(变成 0)

原来:strategy[i] * prices[i] 现在:0 增量:- strategy[i] * prices[i]

🔹 后半段(变成卖出)

原来:strategy[i] * prices[i] 现在:+prices[i] 增量:(1 - strategy[i]) * prices[i]

✅ 单次修改的总增量

[
\Delta =
\sum_{前半段} (-strategy[i] \cdot prices[i])
+
\sum_{后半段} ((1 - strategy[i]) \cdot prices[i])
]


四、算法思路(滑动窗口)

为什么用滑动窗口?

  • 区间长度固定为k
  • 要枚举所有连续长度为k的区间
  • 每次移动只加减一个元素

👉O(n)


核心变量

  • baseProfit:不修改的利润
  • delta:当前窗口的利润增量
  • maxDelta:所有窗口中最大的增量

滑动时怎么更新?

设当前窗口[i - k + 1, i]

新进入的元素i

  • i在后半段 → 加(1 - strategy[i]) * prices[i]

移出的元素i - k

  • 若它原来在前半段 → 减-strategy[x] * prices[x]
  • 若在后半段 → 减(1 - strategy[x]) * prices[x]

五、完整 Java 实现(带详细注释)

classSolution{publiclongmaxProfit(int[]prices,int[]strategy,intk){intn=prices.length;// 1. 计算原始利润longbaseProfit=0;for(inti=0;i<n;i++){baseProfit+=(long)strategy[i]*prices[i];}// 如果 k 为 0 或无法修改if(k==0||k>n){returnbaseProfit;}inthalf=k/2;longdelta=0;longmaxDelta=0;// 2. 初始化第一个窗口 [0, k-1]for(inti=0;i<k;i++){if(i<half){// 前半段 → 变成 0delta+=-(long)strategy[i]*prices[i];}else{// 后半段 → 变成卖出delta+=(long)(1-strategy[i])*prices[i];}}maxDelta=Math.max(0,delta);// 3. 滑动窗口for(inti=k;i<n;i++){intout=i-k;// 移除 outif(out<out+half){delta-=-(long)strategy[out]*prices[out];}else{delta-=(long)(1-strategy[out])*prices[out];}// 加入 iif(i<out+k-half){delta+=-(long)strategy[i]*prices[i];}else{delta+=(long)(1-strategy[i])*prices[i];}maxDelta=Math.max(maxDelta,delta);}// 4. 原始利润 + 最佳增量returnbaseProfit+maxDelta;}}

六、复杂度分析

项目复杂度
时间O(n)
空间O(1)

七、为什么这题是「中等」但难度偏高?

  1. 题目描述是业务语言

  2. 真正考的是:

    • 数学建模能力
    • 把“策略变化”转为“区间增量”
  3. 很多人卡在:

    • 不知道“利润增量”怎么计算
    • 想 DP,其实不需要

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询