买卖股票的最佳时机
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
提示:
1 <= prices.length <= 105
0 <= prices[i] <= 104
第一种:动态规划
根据分析可以得到动态转移方程
dp[i] = Math.Max(dp[i - 1], prices[i] - minPrice);
using System;
using System.Collections.Generic;
public class Solution
{
public int MaxProfit(List<int> prices)
{
int n = prices.Count;
if (n == 0) return 0; // 边界条件
int minPrice = prices[0];
List<int> dp = new List<int>(new int[n]); // 初始化 dp 数组
for (int i = 1; i < n; i++)
{
minPrice = Math.Min(minPrice, prices[i]);
dp[i] = Math.Max(dp[i - 1], prices[i] - minPrice);
}
return dp[n - 1];
}
}
// 示例用法
public class Program
{
public static void Main()
{
Solution solution = new Solution();
List<int> prices = new List<int> { 7, 1, 5, 3, 6, 4 };
int maxProfit = solution.MaxProfit(prices);
Console.WriteLine("最大利润: " + maxProfit); // 输出最大利润
}
}
复杂度分析:
时间复杂度:O(N)
空间复杂度:O(N)
通过复杂度分析,可知实际上我们不需要维护一个dp,只需要维护一个最大值即可,所以可进一步优化代码,从而得到下面这种方式
//通过两个参数,在遍历的过程中获取最大的利润和最小的价格,一次遍历,如果第i天卖出股票,则最大利润为(该天的股价-前面天数中最小的股价),然后与已知的最大利润比较,如果大于则更新当前最大利润的值,动态规划
static public int MaxProfit1(int[] prices)
{
int maxPorfit = 0;
int minPrice = int.MaxValue;
for (int i = 0; i < prices.Length; i++)
{
//动态规划,当前状态由之前的状态推导出来
maxPorfit = Math.Max(maxPorfit, prices[i] - minPrice);
minPrice = Math.Min(minPrice, prices[i]);
}
return maxPorfit;
}
时间复杂度:O(N)
空间复杂度:O(1)
第二种:单调栈(思路来源)
(不作为商用,主要用于个人学习笔记)
static public int MaxProfit2(int[] prices)
{
int MaxProfit = 0;
List<int> list = new List<int>();
for (int i = 0; i < prices.Length; i++)
{
list.Add(prices[i]);
}
list.Add(-1);
List<int> stack = new List<int>();
//prices.SetValue(-1, prices.Length - 1); // 哨兵,设置哨兵的作用是保证所有的数都可以进行计算,比如递增的数组中,最后的结果将得到0,这并不是我们想要得到的比如[1,2]
for (int i = 0; i < list.Count; i++)
{
while (stack.Count>0 && stack[stack.Count - 1] > list[i])//当出现这种情况的时候就要进行弹出栈并且,计算最大值
{
MaxProfit = Math.Max(MaxProfit, stack[stack.Count - 1] - stack[0]);
stack.RemoveAt(stack.Count - 1);//移除最后一个,直到插入的值大于栈的最后一个
}
stack.Add(list[i]);
}
return MaxProfit;
}
这种解决方式,仅仅作为思路拓展,实际上还是动态规划,只是形式不一样,和动规没什么太大区别,且空间和时间复杂度大于动规
空间复杂度分析
列表 list: 我们创建了一个额外的列表 list,它的大小为 n + 1(原始价格数组加上一个哨兵值),因此空间复杂度为 O(n)。
栈 stack: 在最坏情况下,栈 stack 也可能存储所有的价格,因此栈的空间复杂度也是 O(n)。
整个方法的空间复杂度为 O(n)。
结论
时间复杂度: O(n)
空间复杂度: O(n)
在unity中
在Unity游戏开发中,MaxProfit1
方法可以用于多种场景,特别是在涉及市场交易、资源管理或经济系统的情况下。以下是一些具体的应用场景:
1. 虚拟市场交易
在游戏中,玩家可能会与NPC(非玩家角色)进行商品交易。例如,玩家可以购买和出售资源(如武器、装备、材料等)。MaxProfit1
方法可以帮助计算在特定时间段内,玩家在交易中能够获得的最大利润。
示例:
- 玩家在不同的时间点购买和出售资源,
prices
数组可以代表这些资源的价格变化。使用MaxProfit1
方法可以帮助玩家决定最佳的交易时机。
2. 资源管理
在一些策略或模拟类游戏中,玩家需要管理资源并在合适的时机进行投资或出售。例如,农场游戏中,玩家可能需要在不同的季节出售作物,价格会随时间波动。
示例:
prices
数组可以表示作物在不同季节的市场价格,使用MaxProfit1
方法可以帮助玩家找到最佳的种植和出售时机,从而最大化收益。
3. 经济系统
在一些角色扮演游戏(RPG)中,游戏可能会有一个动态的经济系统,玩家的行为会影响市场价格。MaxProfit1
方法可以用于分析市场趋势,帮助玩家做出投资决策。
示例:
- 玩家在游戏中通过完成任务、打怪等方式获得金币,
prices
数组可以表示不同时间点的市场价格变化,使用该方法可以帮助玩家决定何时购买或出售物品以获得最大利润。
4. 游戏内物品拍卖
如果游戏中有拍卖系统,玩家可以在拍卖中出价购买物品。MaxProfit1
可以用来分析拍卖过程中物品的价格波动,以帮助玩家决定何时出价。
示例:
prices
数组可以表示物品在拍卖中的价格变化,使用该方法可以帮助玩家找到出价的最佳时机,从而以更低的价格获得物品。
5. 玩家经济活动分析
开发者可以使用此方法分析玩家的经济活动,评估市场的健康状况。例如,了解玩家在某个时间段内的购买行为和市场反应,以便调整游戏的经济机制。
代码示例
在Unity中,可以将 MaxProfit1
方法放在一个管理交易或经济的类中,并在合适的时机调用它。例如:
public class MarketManager : MonoBehaviour
{
public int[] prices; // 价格数组,可以在运行时动态更新
void Start()
{
// 示例价格数据
prices = new int[] { 7, 1, 5, 3, 6, 4 };
int maxProfit = MaxProfit1(prices);
Debug.Log("最大利润: " + maxProfit);
}
static public int MaxProfit1(int[] prices)
{
int maxProfit = 0;
int minPrice = int.MaxValue;
for (int i = 0; i < prices.Length; i++)
{
maxProfit = Math.Max(maxProfit, prices[i] - minPrice);
minPrice = Math.Min(minPrice, prices[i]);
}
return maxProfit;
}
}
总结
MaxProfit1
方法的应用场景十分广泛,尤其是在涉及经济、交易和资源管理的游戏中。通过合理使用该方法,可以为玩家提供更好的经济决策支持,从而提升游戏的可玩性和深度。