LeetCode初级算法的Python实现--动态规划
动态规划的本质是递归;所以做题之前一定要会递归;递归式就是状态转移方程;这里将会介绍使用动态规划做题的思维方式。
统一的做题步骤:
1、用递归的方式写出代码;(此方法写的代码在leetcode中一定会超时)
2、找冗余,去冗余;
3、找边界;
1、爬楼梯
假设你正在爬楼梯。需要 n 步你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.1 步 + 1 步
2.2 步
写递归
通常情况下,我们会将问题从大到小处理,也就是这里如果有n个台阶,先处理第n个台阶,然后处理n-1,n-2;所以在这里,总体思路是:第n个台阶可以走1步,也可以走两步,当走第一步时,n-1个台阶又可以分为n-1和n-2,不断递归,所以可写为recursionClimbStairs(n - 1),当n台阶走2步时,recursionClimbStairs(n - 2),然后将两种情况相加;示意图如下图所示:
递归代码如下:
def recursionClimbStairs(self, n):
if n <= 2:
return n
return self.recursionClimbStairs(n - 1) + self.recursionClimbStairs(n - 2)
去冗余:
从上图可知,左下角的n-2和右边的n-2重复了,都进行了计算,所以严重拉长的时间;所以,我们可以把计算了的存起来;首先定义数组nums,当n为1时,方法只有一种,当n为2时,方法有两种,所以nums的前两个值分别为1、2;然后从2到n开始循环,当前值为把上面的递归抄下来即可,就是把方法名改成nums,因为存起来了;所以,数组最后的那个值就是最后的答案;如果不理解,仔细把下面几道题按照这种思虑去写,多写几次就理解了。
找边界
因为循环中有n-2,所以n<=2的情况都需要在循环前写好;
def climbStairs(self, n):
nums = [1, 2]
if n <= 2:
return n
for i in range(2, n):
nums.append(nums[i - 1] + nums[i - 2])
return nums[len(nums) - 1]
2、买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
写递归
从最后第n个数开始,第n个数减去前n-1个数的最小值为当前递归层的最大利益,然后将每层的最大利益再去较大值;代码如下
递归代码如下:
def recursionMaxProfix(self, prices):
if len(prices) < 2:
return 0
return max(prices[- 1] - min(prices[:- 1]),
self.recursionMaxProfix(prices[:- 1]))
去冗余:
前1个数利益为0,这里result用来存结果,转换方法和上面那个例子一样,但是其实如果直接使用上面的递归转换的代码为max(prices[i] - min(prices[:i]), result[i - 1]),但是由于min(prices[:i])又是一层循环所以会导致时间又超时,所以这里可以优化为从第一个数开始就获取最小的值存起来,如下代码所示;
找边界
当列表的数值小于2个时,结果只可能为0;
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
result = [0]
if len(prices) < 2:
return 0
minPrice = prices[0]
for i in range(1, len(prices)):
minPrice = min(minPrice, prices[i - 1])
result.append(max(prices[i] - minPrice, result[i - 1]))
return result[-1]
3、最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例 1:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
写递归
思想:从最后第n-1个数开始,所以列表从右到左开始加,反之也可以,但里面的代码要改,思想不变;
递归代码如下:
def recursionMaxSubArray(self, idx, nums, maxSum):
if idx < 0:
return maxSum
nums[idx] = max(nums[idx], nums[idx + 1] + nums[idx])
maxSum = max(nums[idx], maxSum)
return self.recursionMaxSubArray(idx - 1, nums, maxSum)
去冗余:
递归是从第n个数开始,循环可以从左到右,递归中使用了maxSum变量存储最大值,而在这里循环中可直接使用数组,和上面的例子相似,但是由于这里的nums变量循环的时候没有用到前面的值,所以直接存入nums中,代码如下所示;
找边界
因为循环中有i-1,且第0个数也不需要计算,所以直接从1开始循环即可;
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for i in range(1, len(nums)):
nums[i] = max(nums[i] + nums[i - 1], nums[i])
return max(nums)
4、打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
示例 1:
输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
写递归
因为必须相隔一个数,且每个数都是非负的,所以情况分为两种,一种从第一个数开始,一种从第二数开始;两种情况分别递归取较大值;从最后第n个数开始,第n个数加上n-2位置的递归和n-1的递归相比取较大值;代码如下
递归代码如下:
def recursionRob(self, idx, nums):
if idx < 0:
return 0
return max(nums[idx] + self.recursionRob(idx - 2, nums), self.recursionRob(idx - 1, nums))
去冗余:
直接将上述的方法名改成数值即可,如下代码所示;
找边界
因为循环中有i-2,所以列表长度为2之前的需要处理;
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 0:
return 0
if len(nums) == 1:
return nums[0]
nums[1] = max(nums[0], nums[1])
for i in range(2, len(nums)):
nums[i] = max(nums[i] + nums[i - 2], nums[i - 1])
return nums[len(nums) - 1]
LeetCode初级算法的Python实现--动态规划的更多相关文章
- LeetCode初级算法的Python实现--排序和搜索、设计问题、数学及其他
LeetCode初级算法的Python实现--排序和搜索.设计问题.数学及其他 1.排序和搜索 class Solution(object): # 合并两个有序数组 def merge(self, n ...
- LeetCode初级算法的Python实现--链表
LeetCode初级算法的Python实现--链表 之前没有接触过Python编写的链表,所以这里记录一下思路.这里前面的代码是和leetcode中的一样,因为做题需要调用,所以下面会给出. 首先定义 ...
- LeetCode初级算法的Python实现--字符串
LeetCode初级算法的Python实现--字符串 # 反转字符串 def reverseString(s): return s[::-1] # 颠倒数字 def reverse(x): if x ...
- LeetCode初级算法的Python实现--数组
LeetCode初级算法的Python实现--数组 # -*- coding: utf-8 -*- """ @Created on 2018/6/3 17:06 @aut ...
- LeetCode初级算法--动态规划01:爬楼梯
LeetCode初级算法--动态规划01:爬楼梯 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net ...
- LeetCode初级算法--数组01:只出现一次的数字
LeetCode初级算法--数组01:只出现一次的数字 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...
- LeetCode初级算法--数组02:旋转数组
LeetCode初级算法--数组02:旋转数组 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ ...
- LeetCode初级算法--字符串01:反转字符串
LeetCode初级算法--字符串01:反转字符串 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...
- LeetCode初级算法--链表01:反转链表
LeetCode初级算法--链表01:反转链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ ...
随机推荐
- Grunt 使用(二)uglify插件压缩javascript代码
本文在配置grunt基本环境的基础下,讲解如何使用grunt-contrib-uglify进行javascript压缩 本文只介绍了grunt-contrib-uglify插件的一种压缩方式适用于大部 ...
- Linux文件的I/O操作
C标准函数与系统函数的区别 标准函数printf调用应用层api,然后应用层api调用内核层api,再通过内核层api调用硬件设备 一个pirntf打印helloworld那么sys_writ ...
- yii2.0中解决post的400错误
不想用gii的表单自己写表单,但是又遇到了400错误,怎么解决?下面为你解答一下:
- gogs配置及迁移
工作需要迁移gogs,粗略记下笔记 操作系统:CentOS Linux release 7.4.1708 (Core) 防火墙:关闭状态,如有需要开启默认的3000端口 一.配置 首先安装git [r ...
- February 4 2017 Week 5 Saturday
It takes a great man to be a good listener. 懂得倾听的人才是真的了不起. Don't make comments before you have learn ...
- 【海龟汤策略】反趋势交易策略源代码分享(基于BOTVS)
策略介绍: 海龟之汤,简称“龟汤”,是个与海龟交易法则相反的交易策略,它利用了跟势交易(特别是海龟方式)在很多假突破方面的缺陷来获利(把海龟做成汤吃掉).上世纪八十年代早期,有个非常著名的交易员团体— ...
- 杜比(dolby)自动关闭,windows10声音自动变小
电脑问题描述:2018.01.21 win10更新后,看视频电脑声音自动变小,重开机电脑声音正常,一会又会变小.找了很多网上的东西,实践后发现是杜比(dolby)自动关闭导致的,自动关闭的原因是因为切 ...
- EOF及相关函数
结论:EOF是在头文件stdio.h中预定义的一个宏,而eof(end of file)是一个与标准输入/输出流相关联的标志位.当文件指针已经指向文件尾且再次尝试读取时,eof标志会被设置.同时,某些 ...
- jq实现随机显示部分图片在页面上(兼容IE5)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 在powerdesigner 中出现Could not Initialize JavaVM! 应该怎么解决
利用powerdesigner反向生成表结构时会报这个错: 请检查你的环境变量配置: 系统变量 CLASSPATH = E:\Workspaces\my-jar\mysql-connector-jav ...