1. 题目
给定一个数组 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。
2. 解题思路
可以即遍历一次数组,记录并更新所见过的最低价格,同时计算当前价格下的最大利润。每天的价格与最低价格作比较,如果小于最低价格,则更新最低价格;然后用当前价格减去最低价格则是当前利润,如果如果这个利润比之前记录的最大利润还要大,我们就更新最大利润。
初始化变量:首先,我们需要两个变量,一个用于记录到目前为止所见的最低股票价格(
minPrice
),另一个用于记录到目前为止可以获得的最大利润(maxProfit
)。一开始,我们将最大利润设置为0,因为没有进行任何交易,最低价格设置为第一天股票的价格。遍历数组:从第二天开始,我们逐个检查股票的价格。
更新最低价格:对于每一天的价格,我们首先与目前记录的最低价格比较。如果当前天的价格比已知最低价格还要低,我们就更新最低价格。这样做是因为如果未来某一天的价格上涨,我们希望以尽可能低的价格购买股票。
计算并更新最大利润:接下来,我们用当前天的价格减去最低价格,得到如果在这一天卖出股票能获得的利润。如果这个利润比之前记录的最大利润还要大,我们就更新最大利润。
返回结果:当遍历完成后,
maxProfit
变量中存储的就是我们可以从这笔交易中获取的最大利润。这样只需要遍历一次数组,时间复杂度为 O(n),空间复杂度为 O(1)。
int maxProfit(int* prices, int pricesSize) {
if (pricesSize < 2) {
// 如果数组中少于两天价格,则无法进行交易
return 0;
}
int maxProfit = 0; // 最大利润初始化为0
int minPrice = prices[0]; // 最小价格初始化为第一天的价格
for (int i = 1; i < pricesSize; i++) {
if (prices[i] < minPrice) {
// 更新最小价格
minPrice = prices[i];
} else if (prices[i] - minPrice > maxProfit) {
// 更新最大利润
maxProfit = prices[i] - minPrice;
}
}
return maxProfit;
}
在C语言标准库
math.h
中存在fmin()和fmax()函数。用于计算两个指定数值中的最小值和最大值。
fmin()
函数用于返回两个数值中的最小值。其函数原型如下:double fmin(double x, double y); float fminf(float x, float y); long double fminl(long double x, long double y);
如果参数是不同类型的浮点数,比如
float
和double
,那么较小的类型将会被提升到较大的类型,然后进行比较。
fmax()
函数用于返回两个数值中的最大值。其函数原型如下:double fmax(double x, double y); float fmaxf(float x, float y); long double fmaxl(long double x, long double y);
同样,如果参数类型不同,较小的类型会被提升到较大的类型进行比较。
这样可以减少代码量,直接返回两个数值中最小值和最大值,不需要if进行判断。修改后的代码如下:
int maxProfit(int* prices, int pricesSize) {
if (pricesSize==0)
{
return 0;
}
int minprice=prices[0];
int maxProfit=0;
for(int i=1;i<pricesSize;i++)
{
minprice=fmin(minprice,prices[i]);
maxProfit=fmax(maxProfit,prices[i]-minprice);
}
return maxProfit;
}