线性查找-股票最佳收益

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/teaspring/article/details/17732739

题目一:已知一个整型数组,表示某只股票在每天的价格(假定每天价格保持一定,并且可买入可卖出),如果只允许买入一次卖出一次, 问最佳受益是多少?

这题跟数组最大距离恰成互补,这题简化之后就是 已知A[n], 问找到 j > i, 使得A[j] - A[i] 最大。(数组最大距离是 找到 A[j] > A[i], 使得 j-i 最大)

要求A[j] - A[i] 最大,我们如果以j从0起始遍历,无非就是让A[j] 跟左边元素中的最小值Lmin相比,显然Lmin可以在j遍历过程中不断更新,所以这里的线性查找就呼之欲出了。

int bestbuysellstock01(const int *A, int n, int& buy, int& sell){
    int min=0, maxDiff=0;
    buy = sell = 0;
    for(int i=1;i<n;++i){
        if(A[i] < A[min]){
            min = i;
        }else{
            int diff = A[i] - A[min];
            if(diff > maxDiff){
                maxDiff = diff;
                buy = min;
                sell = i;
            }
        }
    }
    return maxDiff;
}

很自然,用手指头想想都能想到题目二:如果不限制交易次数,那么最佳收益应该是多少?

唔,一次买入卖出是O(n),那么多次交易貌似是O(n^2), 动态规划??别急,我们来看看真实情况。

                                                         图一,上证指数日k线图

很清楚了吧?我们只要把每一段上涨都牢牢抓住,每段收益(比如图一中圈出的区间)都收入囊中,那就是最大收益!所以,依然是线性,依然是一次遍历

int keepbuysellstock(int *A, int n){
    int sum=0, buy=0, sell=0;
    for(int i=1;i<n;++i){
        if(A[i] >= A[i-1]){ //increasing
            if(buy == sell){
                buy = i-1;
            }
            sell = i;
        }else{ //falling down
            if(sell > buy){
                sum += A[sell] - A[buy];
                sell = buy = i-1;
            }
        }
    }
    if(sell > buy)
        sum += A[sell] - A[buy];
    return sum;
}

代码实现中,关键在于极值点的处理:

1. “底部过后方知是底”,今日价格首次高于昨日价格时,昨日价格才是局部底;

2. “顶部过后方知是顶”,今日价格首次低于昨日价格时,昨日价格才是局部顶。

好吧,这道题对于投资过股票的人来说,实在是太亲切了:)


注:题目一来自leetcode, 题目二在评论中也有出现,有个人说面试中面试官在出了题目一后紧接着出了题目二,然后他还没做对。。。所以,不要被题目吓死啊


猜你喜欢

转载自blog.csdn.net/teaspring/article/details/17732739