121.买卖股票的最佳时机
给定一个数组 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。
根据题目意思,就是找到差值最大的两个数(要求被减数在先出现)
方法一:笨笨的咔咔遍历
既如此就互相试呗
class Solution {
public:
int maxProfit(vector<int>& prices) {
int max=0;
for(int j=0;j<prices.size();j++)
{
for(int i=j+1;i<prices.size();i++)
{
if(prices[i]-prices[j]>max)
max=prices[i]-prices[j];
}
}
return max;
}
};
这个方法的弊端也是有目共睹哈,当数据量非常庞大的时候就会执行超时,因为这需要对任意两个数进行比较,时间复杂度比较高o(n!)(不知道我算的对不对)
方法二:
尝试少一层循环呢?我们的思路是:找到前边的大一点的值,减去后边小一点的值,差值最大。不妨将整个数组切割成两部分,比如[7,1,5,3,6,4],假设我们从中间划分的话,如果买股票的时机出现在[7,1,5]这三个元素里,卖股票时机出现在[3,6,4]的这三个元素里,那么我们只需要找到前半部分的最小值和后半部分的最大值就可以了,问题是这个前边和后边如何定义呢?毕竟我们不是带广角的上帝,所以可以尝试从不同的地方将数组进行分割,上边是假设从中间开始,如果我们从第一个元素后开始分割(别从头开始分割啊,没有意义,因为买和卖都要有值):[7**/**1,5,3,6,4],再从第二/第三个元素后分割,直到倒数第一个元素之前,能够找到每种分割后前后两个数组的最大/最小值,再求出差值,就能得到利润了。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int max=0,len=prices.size();
auto max_it=prices.begin(),min_it=prices.begin();
vector<int>::iterator i=prices.begin()+1;
if(len==0 ||len==1)
return 0;
for(i;i!=prices.end();i++)
{
min_it =min_element(prices.begin(), i+1);
max_it =max_element(i, prices.end());
if(*max_it-*min_it>max)
max=*max_it-*min_it;
}
return max;
}
};
其实这段代码逻辑上没问题,但是执行起来是超时的🥲因为小小的min_element和max_element方法是计算机偷偷排序取到的,就很耗时。
方法三:官方大大 法
呜呜呜,不愧是官方发大大!!!我现在整理这道题还要再思考半天。
基于方法二的思考我们需要知道前边的最小值和后边的最大值,不用max_element方法,我们可以在遍历的过程中记录一下遇到的最小值pre,再用遍历的当前值prices[i]减去记录到的最小值,就能得到目前的最大利润,就这样遍历到最后,就能得到答案了👍👍👍非常秒。
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()==0 ||prices.size()==1)
return 0;
int pre = prices[0], ans = 0;//ans是当前利润,pre记录遍历过程中的最小元素值
for (int i = 0; i < prices.size(); i++) {
if(pre>prices[i])
pre=prices[i];//pre记录遍历过程中的最小元素值
if(ans<prices[i]-pre)//计算当前值减去最小值(pre代表遍历过程中的最小值)也就是利润
ans=prices[i]-pre;
}
return ans;
}
};