1. 项目背景与核心价值
"买橘子"这个看似简单的日常行为,在牛客网的算法题库中被设计成了一道经典的动态规划练习题。这道题最早出现在《剑指Offer》面试题库中,后来被牛客网收录为"每日一题"的精选题目。作为算法面试中的高频考题,它考察的是候选人对于状态转移和最优子结构的理解能力。
在实际面试场景中,这道题通常会以这样的形式出现:给定一个表示橘子价格的数组prices,其中prices[i]代表第i天橘子的价格。你可以进行多次交易(多次买卖同一支橘子),但必须在再次购买前出售掉之前的橘子。设计算法计算你能获得的最大利润。
注意:这道题与著名的"买卖股票的最佳时机"问题属于同类型题目,但增加了"橘子"这个生活化场景,降低了题目的压迫感,更符合国内技术面试的沟通习惯。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题分析与算法选型
2.1 问题抽象化建模
首先我们需要将生活场景转化为数学模型:
- 输入:价格序列 prices = [p1, p2, ..., pn]
- 约束:可以完成任意次交易,但必须卖完才能再买
- 目标:max(∑(sell_price - buy_price))
通过分析可以发现,最大利润实际上就是所有上升区间的累加和。例如价格序列[1,2,3,4,5]的最大利润就是(2-1)+(3-2)+(4-3)+(5-4)=4,等同于5-1=4。
2.2 动态规划解法
定义状态转移方程:
- dp[i][0] 表示第i天不持有橘子时的最大利润
- dp[i][1] 表示第i天持有橘子时的最大利润
状态转移:
python复制dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]) # 前一天不持有或卖出
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]) # 前一天持有或买入
初始化:
python复制dp[0][0] = 0 # 第一天不买
dp[0][1] = -prices[0] # 第一天买入
2.3 贪心算法优化
观察到利润可以分解为每日的差值:
python复制profit = 0
for i in range(1, len(prices)):
if prices
