LeetCode 动态规划《简单》部分 Python实现

#2018-06-07  June Thursday the 23 week, the 158 day SZ
#LeetCode 动态规划简单部分 Python实现
'''

爬楼梯
假设你正在爬楼梯。需要 n 步你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1 步 + 1 步
2.  2 步

示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 步 + 1 步 + 1 步
2.  1 步 + 2 步
3.  2 步 + 1 步

'''
'''
方法:通过
思路:递归法
反着考虑,有几种方案到第i阶楼梯,答案是2种:
1.第i-1阶楼梯经过一步
2.第i-2阶楼梯经过两步
假设count(i)表示到第i阶楼梯方案的个数,则count(i) = count(i-1) + count(i-2) 
这就是大名鼎鼎的斐波那契数列
'''
class Solution(object):
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n ==0 or n==1:
            return 1
        count = [1,1]
        for i in range(2,n+1):
            #count[i] = count[i-1] + count[i-2] #IndexError: list assignment index out of range
            count.append(count[i-1] + count[i-2])

        return count[i]

my_solution = Solution()
a = 1 #UnboundLocalError: local variable 'i' referenced before assignment

b = my_solution.climbStairs(a)
print(b)

'''
买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。


示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
'''

#方法1:超时(如果列表很长)
#思路:双指针循环判断
class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        maxpro = 0
        for i in range(len(prices)):
            for j in range(i+1,len(prices)):
                if prices[j] - prices[i] >maxpro:
                    maxpro  = prices[j] - prices[i]
        return maxpro 

my_solution = Solution()
a = [7,6,4,3,1]

b = my_solution.maxProfit(a)
print(b)

#方法2:错误
#思路:先求最小值,然后求最小值位置,然后用最小值位置后的最大值减去最小值。。。哈哈,一心只求最小值。系统直接让我认知我是傻逼
class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if len(prices) == 0:
            return 0
        buy_price = min(prices) #Line 7: ValueError: min() arg is an empty sequence
        buy_price_day = prices.index(buy_price)
        sell_price = max(prices[buy_price_day:])
        return sell_price - buy_price

my_solution = Solution()
a =[2,4,1]

b = my_solution.maxProfit(a)
print(b)
        
0
[Finished in 0.5s]
#方法3:超时
class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if len(prices) == 0 or len(prices) == 1:
            return 0

        profits = []
        for i in range(len(prices)):
            for j in range(i+1, len(prices)):
                profits.append(prices[j] - prices[i])
        return max(profits) if max(profits) > 0 else 0

my_solution = Solution()
a =[7,6,4,3,1]

b = my_solution.maxProfit(a)
print(b)
        

#方法4:通过
#思路:
class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if len(prices) <2:
            return 0
        min_price = prices[0]
        max_profit = 0
        for i in prices:
            min_price = min([i,min_price])
            max_profit = max(i - min_price, max_profit)
        return max_profit
my_solution = Solution()
a =[7,6,4,3,1]

b = my_solution.maxProfit(a)
print(b)

'''

最大子序和Maximum Subarray
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。


进阶:

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

'''


class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        length=len(nums)
        for i in range(1,length):
            #当前值的大小与前面的值之和比较,若当前值更大,则取当前值,舍弃前面的值之和
            subMaxSum=max(nums[i]+nums[i-1],nums[i])
            nums[i]=subMaxSum#将当前和最大的赋给nums[i],新的nums存储的为和值
        return max(nums)

my_solution = Solution()
a = [2,7,9,3,1]
b = my_solution.maxSubArray(a)
print(b)

'''
打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 1:
输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12 。
'''
'''
#方法1:通过
#思路:这个问题可以这么想,假设只有一家,那么你只能偷这家;假设有两家,那么你要判断两家哪个钱多,偷哪个;假设有三家人,你是偷第三家和第一家还是只偷第二家?
假设有四户人,你偷第四户和前面两户还是只偷第三户?
依次类推,把n-2家以前所有家庭作为一个大家庭,让你决定偷第n家还是偷n-1家
那么你要判断“偷第n家不偷第n-1家且前n-2家尽量多的偷”和“不偷第n家偷n-1家,且前n-1家尽量多的偷”,哪个得到的钱多偷哪个。 
 你可以递归求解,然而复杂度太高无法AC。所以应该记录已经计算过的结果,于是这变成一个动态规划问题。
 '''
class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        if len(nums) == 0:
            return 0
        elif len(nums) <= 2:
            return max(nums)
        #money =[] #IndexError: list assignment index out of range

        #money = [0]*len(nums) #定义一个长度为len(nums)的列表,或者直接定义money = nums,或者这样[0 for i in range(len(num))],全部元素为零的列表,机智

        #money[0], money[1] = nums[0], max(nums[0], nums[1])
        nums[0], nums[1] = nums[0], max(nums[0], nums[1])
        for i in range(2, len(nums)):
            #money[i] = max(nums[i] + money[i-2], money[i-1])
            nums[i] = max(nums[i] + nums[i-2], nums[i-1])  #nums[i]就代表了所偷的所有财富之和
        #return money[len(nums)-1]
        #return nums[len(nums) -1] #等价于nums[i],等价于nums[-1],也就是拿到nums数组的最后一个值
        return nums[i]

my_solution = Solution()
a = [2,7,9,3,1]
b = my_solution.rob(a)
print(b)
12
[Finished in 0.6s]

#方法2:通过

#思路:上面的代码使用的空间是冗余的,因为每次循环只会用到前两个数据。所以代码可以降低空间复杂度到O(1)。
class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        yesterday = last = 0
        for today in nums:
            last, yesterday = yesterday, max(today+last, yesterday)
        return yesterday


my_solution = Solution()
a = [2,7,9,3,1]
b = my_solution.rob(a)
print(b)
12
[Finished in 1.1s]

猜你喜欢

转载自blog.csdn.net/btujack/article/details/80619907
今日推荐