目录
前言
提示:我就是一个运气很好的人,运气爆表
本系列《绝境求生》记录转码算法筑基过程,以代码随想录为纲学习,leetcode_hot_100练手,在此记录思考过程,方便过后复现。内容比较粗糙仅便于笔者厘清思路,复盘总结。
添加了代码逻辑这一部分内容
提示:以下是本篇文章正文内容
动态规划
特点:运筹学上最优化算法,题型是求最值,重叠子问题,最优子结构,!!状态转移方程
把复杂问题拆解成小问题,再由小问题的答案推导出大问题的答案(即记住之前做过的事情,避免重复计算,提高效率)
状态定义:用某个变量或数组代表某个小问题的答案
状态转移方程:大问题的答案=小问题答案的组合的数学表达式
初始化条件:最小的问题,不用推导就知道答案
一、70 爬楼梯
题目描述
示例 1:
ini输入: n = 2 输出: 2 解释: 有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶示例 2:
markdown输入: n = 3 输出: 3 解释: 有三种方法可以爬到楼顶。 1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶
1.模型
简单理解?
一次只能爬1,2个台阶,那爬n阶有几种方法
主要还是代几个子数据去推状态转移方程
能不能用图示意?
None
初始化条件?
定义i 为 第i 阶楼梯
dp[i] 就是爬第i阶楼梯所有方法的数组
d[1]=1 ,d[2]=2 (0-1-2,0- 2)
边界条件?
可以剪枝一下。 比如当i=1或i=2时候直接返回1,2 因为创建数组也没有意义
代码逻辑?
None
用什么方法:暴力法/ 其它巧妙的方法。 巧妙方法的子思路是? 。。。。。??
暴力法
ini
def solution(i):
if i ==1:
return 1
if i ==1:
return 2
#初始化dp数组用dp[0]占位
dp=[0]*(i+1) #因为索引是0-n,所以
d[1]=1
d[2]=2
for _ in range(3,i+1):
dp[i]=dp[i-1]+dp[i-2]
return dp[i] #返回爬到n阶的方法
优化法
用双指针法
用变量替代数组
ini
#爬楼梯的优化法
def solution(i):
if i ==1:
return 1
if i ==1:
return 2
pre_pre=1
pre=2
for _ in range(3,i+1):
cur = pre + pre_pre # 当前i阶的方法数 = 前两阶方法数之和
# 指针前进:为下一次迭代做准备
pre_pre = pre # 原来的prev(i-1)变成新的prev_prev(i-2)
pre = cur # 原来的current(i)变成新的prev(i-1)
# 最终prev就是n阶的方法数(循环结束后,prev对应dp[n])
return pre
细节?
None
之前见过但没注意到的?
创建一个全0数组 dp=[0]*n
疑惑点/新知识 ?
搞清楚索引和数组长度分别定义什么?
自底向上的思路i-2,i-1再到i,不要反过来了
二、118杨辉三角
题目描述
给定一个非负整数 numRows, 生成「杨辉三角」的前 numRows 行。
在**「杨辉三角」**中,每个数是它左上方和右上方的数的和。
编辑
示例 1:
ini输入: numRows = 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2:
lua输入: numRows = 1 输出: [[1]]
1.模型
简单理解?
每个数是左上方和右上方数之和
能不能用图示意?
csharp
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
数组张这样,特点:每一行的首尾元素都是1
初始化条件?
dp=[[1]] 第零行为1
边界条件?
剪枝 numRows=0 输出空列表,为n时要输出n行
代码逻辑?
先初始化首尾,再填中间或者先全初始化 1,再覆盖中间
定义上一行还有当前行,首尾数与边界条件灵活搭配
矩阵构造上是先构造行,再添加每一行到二维数组中,而不是按元素s型构造数组
用什么方法:暴力法/ 其它巧妙的方法。 巧妙方法的子思路是? 。。。。。??
暴力法
ini
def solution(numrows):
if numrows==0:
return []
dp=[[1]] #定义第0行
for i in range(1,numrows): #从第1行开始操作
cur_row=[1] #行首为1 直接是一个列表了 [1,]
pre_row=dp[i-1] #定义上一行
#定义中间数
for j in range(1,i):
cur_val=pre_row[j-1]+pre_row[j]
cur_row.append(cur_val)
cur_row.append(1)
dp.append(cur_row)
return dp
# print(solution(5))
dp=solution(5)
for _ in dp:
print(_,end='\n')
优化法
scss
C(i,j) = i!/(j!*(i-j)!)
C(i,j-1) = i!/((j-1)!*(i-j+1)!)
把 C(i,j) 用 C(i,j-1) 表示:
C(i,j) = C(i,j-1) * (i-j+1) / j
ini
# 用公式法优化
def solution(numrows):
if numrows==0:
return []
result=[]
for i in range(numrows):
row=[1]*(i+1) #初始化当前行,长度为i+1(第i行有i+1个元素),所有元素先设为1 C(i,0),C(i,j)=1
for j in range(1,i):
row[j]=row[j-1]*(i-j+1)//j #数学公式法通过递推法 构建的 C(i,j) = i!/(j!*(i-j)!)
result.append(row)
return result
细节?
None
之前见过但没注意到的?
创建二维数组
append() 可以添加数值也可以添加子向量
我以为 t=[1,]才能是列表
编辑
疑惑点/新知识 ?
杨辉三角的数学公式怎么和递推结合