前沿--股票买卖(亚马逊面试题)

前沿–股票买卖(亚马逊面试题)

一.股票买卖

1.题目描述

设计一个算法,根据给定的股价走势信息,决定买入和卖出策略,该策略必须保证你的交易获得的利润最大化

2.暴力枚举法

检测任何一种可能的买卖组合.例如,第i买进,第j卖出,其中j>i,计算两者差价P(i,j)=S[j]-S[i],并返回计算得到的最大值

s=[10,4,8,7,9,6,2,5,3]

maxProfit=0
buyDay=0
sellDay=0

for i in range(len(s)-1):
    for j in range(i+1,len(s)):
        if s[j]-s[i]>maxProfit:
            maxProfit=s[j]-s[i]
            buyDay=i
            sellDay=j

print("应该在第{0}天买入,第{1}天卖出,最大交易利润为:{2}".format(buyDay+1,sellDay+1,maxProfit))
应该在第2天买入,第5天卖出,最大交易利润为:5

a.性能分析

假定数组S的长度为n,外层循环运行n次,内层循环走n-i-1.因此算法的时间复杂度为:i=0n1(ni1)=n(n1)/2sum_{i=0}^{n-1}(n-i-1)=n(n-1)/2.也就是说暴力枚举法的算法复杂度为O(n2)O(n^2)

3.分而治之法

s分解成两部分。一部分是s的前半部分:s[0:n/2],另一部分是s的后半部分:s[n/2:n],分别计算前半部分和后半部分的最大交易利润,然后在两者中选出最大的一个.但是需要考虑一种跨界情况,那就是最大利润可能实现的方案是:在前半部分的某一天买入,在后半部分的某一天卖出,这种情况我们要在前半部分找到最小值,在后半部分找到最大值,只需要一个循环就可以实现

def findMaxProfit(s):
    if len(s)<2:
        return [0,0,0]

    if len(s)==2:
        if s[1]>s[0]:
            return [0,1,s[1]-s[0]]

        else:
            return [0,0,0]

    firstHalf=findMaxProfit(s[0:int(len(s)/2)])
    secondHalf=findMaxProfit(s[int(len(s)/2):len(s)])
    finalResult=firstHalf

    if secondHalf[2]>firstHalf[2]:
        # 后半部分的交易日期要加上前半部分的天数
        secondHalf[0]+=int(len(s)/2)
        secondHalf[1]+=int(len(s)/2)
        finalResult=secondHalf
    
    # 看最大利润方案是否是在前半部分买入,后半部分卖出
    lowestPrice=s[0]
    highestPrice=s[int(len(s)/2)]
    buyDay=0
    sellDay=int(len(s)/2)

    for i in range(0,int(len(s)/2)):
        if s[i]<lowestPrice:
            buyDay=i
            lowestPrice=s[i]

    for i in range(int(len(s)/2),len(s)):
        if s[i]>highestPrice:
            sellDay=i
            highestPrice=s[i]

    if highestPrice-lowestPrice>finalResult[2]:
        finalResult[0]=buyDay
        finalResult[1]=sellDay
        finalResult[2]=highestPrice-lowestPrice

    return finalResult


s=[10,4,8,7,9,6,2,5,3]

maxprofit=findMaxProfit(s)

print(maxprofit[0]+1,maxprofit[1]+1,maxprofit[2])
2 5 5

a.分析性能

算法把一个大问题先分解成两个子问题加以解决,最后再进行一次大循环,因此算法复杂度公式为:

T(n)=2T(n2)+O(n)T(n)=2T(frac{n}{2})+O(n)

4.最优解法

假设最佳交易方案是第N太难卖出,那么很显然,最佳的买入时机就是前N-1天中价格最低的时候,也就是要在s[0:N]中的最小值时买入.如果把最小值记为Min(s[0:N],那么最大利润就是profit=s[N]-Min(s[0:N]).因此我们可以将N从1遍历到n,然后找出最大利润,此时只需遍历数组一次就可以完成

from IPython.display import Image

Image(filename="./data/1_1.png",width=800)

output_16_0.png

s=[10,4,8,7,9,6,2,5,3]

maxprofit=0
leftmin=s[0]

buyDay=0
sellDay=0
tmp=0

for i in range(len(s)):
    if s[i]<leftmin:
        leftmin=s[i]
        tmp=i

    if s[i]-leftmin>maxprofit:
        maxprofit=s[i]-leftmin
        buyDay=tmp
        sellDay=i

print("应该在第{0}天买入,第{1}天卖出,最大交易利润为:{2}".format(buyDay+1,sellDay+1,maxprofit))
应该在第2天买入,第5天卖出,最大交易利润为:5

a.性能分析

这种方法只需把数组遍历一次,因此时间复杂度为O(n),它的效率最高

原文地址:https://www.cnblogs.com/LQ6H/p/12940553.html