买卖股票最佳时机1-4加注释

1:
主要思想:dp(最大和子数组)

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        lenth = len(prices)
        if lenth == 1 or lenth == 0:
            return 0
        newlst = []
        for i in range(1,lenth):
            newelement = prices[i] - prices[i-1]  # 按照算法导论上的思想,把原来存放每一天股票价格的数组,转换成存放股票价格波动的数组
            newlst.append(newelement)
        # 接下来利用动态规划思想,即考虑newlst这个数组,简称n数组。在n数组上迭代更新
        # 最后得到n[j]存放的是,以下标j的元素为结尾的子数组的最大和。
        for j in range(1,lenth-1):
            newlst[j] = newlst[j] + max(0,newlst[j-1])
        res = max(newlst)
        # return res >= 0 and res or 0
        return res if res > 0 else 0

2:
主要思想:贪心算法

# 由于买卖次数不限,则先采取1中的转换数组,然后遍历newlst,把大于0的元素都加起来就行。
# 其实,newlst大可不必,只要在第一个循环里
# 把所有prices[i] - prices[i-1]大于0的结果统计起来就行
class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        lenth = len(prices)
        if lenth == 1 or lenth == 0:
            return 0
        newlst = []
        for i in range(1,lenth):
            newelement = prices[i] - prices[i-1]
            newlst.append(newelement)
        res = 0
        for j in range(0,lenth-1):
            if newlst[j] > 0:
                res += newlst[j]
        return res

3:
主要思想:dp

# 最多买卖两次
# 看到有一种解法是创建两个dp[]数组(记为dp1、dp2),分别从前向后遍历、从后向前遍历。
# 其中,对于dp1,从前向后遍历,使得dp1[i]记录的是
# 从1到i天可以获得的最大利益,在i这个位置可以选择是否卖出手中股票。
# 对于dp2,从后向前遍历,使得dp2[i]记录的是
# 从i到最后一天中可以获得的最大利益,在i这个位置可以选择是否买股票。
# 最后选择dp1+dp2数组中的最大元素。
#----------
# 下面算法,创建了四个变量,分别代表
# 第一次买股票之后欠了最少多少钱(但由于取的是负数,所以也用max函数)
# 第一次卖股票之后手里最多有多少钱
# 第二次买股票之后最少欠了多少钱(同第一个变量,用max)
# 第二次卖股票之后手里最多有多少钱。
# 显然,第二次买股票之后手里最多有多少钱就是问题的解
class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        lenth = len(prices)
        if lenth == 0:
            return 0
        buy1 = -prices[0]
        sell1 = 0
        buy2 = -prices[0]   # sell1 + buy1
        sell2 = 0
        for i in range(1,lenth):
            buy1 = max(buy1,-prices[i])
            sell1 = max(sell1,prices[i]+buy1)
            buy2 = max(buy2,-prices[i]+sell1)
            sell2 = max(sell2,prices[i]+buy2)
        return sell2

4:
主要思想:dp + k>prices.length时的考虑以避免超出内测限制

# 第四个跟第三个思路一摸一样,只是k不限制<=2。
# 与上题一样,需要创建 2*k个变量,分别表示
# 第一次买股票之后欠了最少多少钱
# 第一次卖股票之后手里最多有多少钱
# 第二次买股票之后欠了最少多少钱
# 第二次卖股票之后手里最多有多少钱;一直到k...
# 采用这种思想,大概可以通过leetcode上200个样例,但是,当k特别大的时候,内存就超了。
# 事实上,一次买一次卖,必须要用两天,所以当k >= lenth/2的时候,其实就转换成了第二题
# 即,一个就lenth天,k>=lenth/2,其实可以每天都买卖股票
# 也就转换成了一个贪心问题,只要把所有前后两天价格差为正数的情况都算进去就行了。
class Solution(object):
    def greedy(self,prices):
        res = 0
        lenth = len(prices)
        res = 0
        for i in range(1,lenth):
            if prices[i] - prices[i-1] > 0:
                res += prices[i] - prices[i-1]
        return res
    def maxProfit(self, k, prices):
        """
        :type k: int
        :type prices: List[int]
        :rtype: int
        """
        lenth = len(prices)
        if lenth == 0 or k == 0:
            return 0
        if k >= lenth/2:
            return self.greedy(prices)
        res = [[-prices[0],0] for i in range(k)]  # return res[k-1][1]
        # print(res)
        for i in range(1,lenth):
            res[0][0] = max(res[0][0],-prices[i])
            res[0][1] = max(res[0][1],res[0][0]+prices[i])
            for j in range(1,k):
                res[j][0] = max(res[j][0],res[j-1][1]-prices[i])
                res[j][1] = max(res[j][1],res[j][0]+prices[i])
        return res[k-1][1]
发布了45 篇原创文章 · 获赞 0 · 访问量 976

猜你喜欢

转载自blog.csdn.net/jokerxsy/article/details/104900204