Best Time to Buy and Sell Stock

题目:

数组中某数字减去其左边的某数字得到一个数对之差,求所有数对之差的最大值。

例如:数组{2, 4, 1, 16, 7, 5, 11, 9}中,数对之差的最大值是15(16 - 1)

分析:看到这个题目,很多人的第一反应是找到这个数组的最大值和最小值,然后觉得最大值减去最小值就是最终的结果。

但由于我们无法保证最大值一定位于数组的右边。

让每一个数字逐个减去它左边的所有数字,并通过比较得到数对之差的最大值,总的时间复杂度是O(n2)

解法一:转化为求子数组的最大和问题

可以转化为求子数组的最大和问题。

1、有一数组array[n],数组长度为n

2、构建一个长度为n-1的辅助数组tmp[n-1],且tmp[i] = array[i] - array[i-1]; (1<=i<n),tmo[0]=0;

3、如果累加辅助数组tmp从i到j(j>i),即tmp[i] + tmp[i+1] + ... + tmp[j],

有(array[i] - array[i-1]) + (array[i+1] -array[i]) + ... + (array[j] - array[j-1]) = array[j] - array[i-1]

分析至此,发现数组中最大的数对之差(即array[j] - array[i-1])其实是辅助数组tmp中最大的连续子数组之和。

如何求连续子数组最大之和,

即为  sum[i+1] = max( sum[i]+tmp[i+1] , tmp[i+1] , sum[i] ); 其中sum[i]表示tmp数组0~i的最大连续子数组和。

可分为两种情况:如果sum[i]包含tmp[i],则sum[i+1]是 sum[i]与sum[i]+tmp[i+1]的较大者;

                如果sum[i]不包含tmp[i],则sum[i+1]是 sum[i]与tmp[i+1]的较大者。

可以简化为:如果sum[i]>0 ,则 sum[i+1]=sum[i]+tmp[i+1];(这里比较sum[i]+tmp[i+1] 和 tmp[i+1]

                        否则sum[i+1]=tmp[i+1];

            再将sum[i+1]与sum[i]比较。

同时可以将数组sum[i]用一个变量表示。

具体实现:

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(prices.size()<=0)
           return 0;
        vector<int> tmpvec(prices.size());
        tmpvec[0]=0;
        for(int i=1; i<prices.size() ; i++)
            tmpvec[i] = prices[i]-prices[i-1];
        int max=0;
        int t=0;
        for(int j=0;j<tmpvec.size();j++)
        {
            if(t>0)
                t = t+tmpvec[j];
            else
                t = tmpvec[j];
            if(t>max)
                max = t;
        }    
   
        return max; 
    }
};

解法二:动态规划

对于数组array[i],我们只需求的 array[i] 与 前面 0~i-1 之间的最小值做差,求的最大的差。

即 tmp[i] = array[i] - min(array[0~i-1])

所以我们遍历时,需要时刻更新当前的min,以及最大差。

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(prices.size()<=1)
           return 0;
        int i=0, j=1;
        int minda = prices[0];
        int max = prices[j]-minda;
        for(j=1;j<prices.size();j++)
        {
            if(prices[j]<minda)
                minda = prices[j];    
            if(prices[j]-minda>max)
                max = prices[j]-minda;        
        }    
        return max; 
    }
};

其中 minda 表示 当前最小元素,max 表示最大差。
 

实现三:

class Solution {  
public:  
    int maxProfit(vector<int> &prices) {  
        // Start typing your C/C++ solution below   
        // DO NOT write int main() function   
        if(prices.size()<=1)  
           return 0;  
        int minda = prices[0];  
        int max = 0;  
        for(int j=1;j<prices.size();j++)  
        {       
            if(prices[j]-minda>max)  
                max = prices[j]-minda;   
            if(prices[j]<minda)  
                minda = prices[j];        
        }      
        return max;   
    }  
};


 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值