Leetcode--DP

32. Longest Valid Parentheses

dp[i] = dp[start - 1] + (i - start + 1): dp[i]表示到第i个位置为止的有效括号长度,dp[start - 1]表示在start之前的有效括号长度,i - start + 1表示从i到start中间的有效括号长度,start是从栈里pop出来与右括号相对应的左括号,i是当前右括号的下标
if s[i] == '(': stack.append(i),注意存放的是左括号下标
else: if stack: start = stack.pop() 如果遇到了右括号,且栈不为空,就从stack里pop出一个左括号的下标作为start
注意最后返回的是max(dp)

53. Maximum Subarray

假设我们已知第i步的global[i](全局最优)和local[i](局部最优),那么第i+1步的表达式是:
local[i+1]=Math.max(A[i], local[i]+A[i]),就是局部最优是一定要包含当前元素,所以不然就是上一步的局部最优local[i]+当前元素A[i](因为local[i]一定包含第i个元素,所以不违反条件),但是如果local[i]是负的,那么加上他就不如不需要的,所以不然就是直接用A[i];
global[i+1]=Math(local[i+1],global[i]),有了当前一步的局部最优,那么全局最优就是当前的局部最优或者还是原来的全局最优(所有情况都会被涵盖进来,因为最优的解如果不包含当前元素,那么前面会被维护在全局最优里面,如果包含当前元素,那么就是这个局部最优)

70. Climbing Stairs

这道题目是求跑楼梯的可行解法数量。每一步可以爬一格或者两个楼梯,可以发现,递推式是f(n)=f(n-1)+f(n-2),也就是等于前一格的可行数量加上前两格的可行数量。熟悉的朋友可能发现了,这个递归式正是[斐波那契数列]

注意当n==0时,也返回1. 初始化时,dp[0]=1, dp[1] = 2, 是从0和1开始,不是从1和2开始。
follow up是有没有更好的解法: 有,O(logn),使用斐波那契的通项公式

general term formula
Follow up实现

91. Decode Ways

dp[i]存储的是加入s中第i-1个元素后有多少种decode方式,所以dp[]初始化时的长度要比s多一位,并且使dp[0]=1

  • 注意,0只能出现在1或者2后边,构成10,20,如果单独出现的0,则无法解析
  • 如果字符s[i-1]不为0,则这个字符可以独立地被解析,例如:1-9,dp[i] += dp[i-1]
  • 如果字符s[i-2:i]大于'09'且小于'27',证明i-1位字符和i-2位字符可以放在一起被解析,dp[i] += dp[i-2]
  • dp[i-2:i] < '27'这是按ASCII码值来比较的,python中可以对字符串进行比较,都是先将其转换为ASCII码值。其中,大写字母的值都小于小写字母,同时('ab'<'abc')即空位的序数为所有字符最小
  • 最后返回dp[-1]

96. Unique Binary Search Trees

这道题在树的分类里已经写过了,但还是有些细节需要添加。

  • res数组要初始化n+1位,因为包括0在内了,并且res[0]和res[1]都要初始化为1,其余均为0
  • res[i]+= res[j]*res[i-j-1], res[j]代表i左边的left branch数量,res[i-j-1]代表right branch数量。j是i左边的node个数,i-j-1是i右边的node个数,因为n是顺序分解的,所以个数相同,生成的BST就相同。
  • 注意外层for循环i的范围:for i in range(2, n+1):
  • 最后返回res[n]

95. Unique Binary Search Trees II

虽然在dp分类里,但其实更偏向于divide and conquer

  • 构建一个生产子树的函数,参数为start, end,分别等于1和n
  • 在这个函数内,如果start>end,就返回[None], 括号里一定要有none, 如果start==end, 就返回[TreeNode(start)]
  • for i in range(start, end+1), end要加1
  • leftsubtree = self.generate(start, i-1), rightsubtree = self.generate(i+1, end)
  • 在for循环前要初始化res = []
  • 将左右子树用两个for循环排列组合起来,要先root = TreeNode(i), 每组合成功一个后就res.append(root)

120. Triangle

这道题之前也写过了,需要注意的点有:

  • res初始化时的长度为triangle最后一行的长度再加1,加1是因为如果triangle里只有一行,那就超出了递归式里的索引范围
  • 思路是将triangle reverse,然后针对每一行(倒序)里的每一个数字,更新res[i],等于当前数字,加上一组的min(res[i], res[i+1])
  • 最后返回res[0], 因为第一行只有一个数字

121. Best Time to Buy and Sell Stock

又是局部最优,全局最优方法。初始化local和res均为0, 先判断数组是不是递减的,如果是就返回0if sorted(prices) == prices[::-1]: return 0
若不是递减的,针对数组中每一个数字,计算
local = max(0, local + prices[i+1] - prices[i]), res = max(res, local)

  • i的循环范围是for i in range(len(prices)-1), 因为后边有i+1
  • 更新local时,应该加上原来的Local, 和0比较是因为价格有可能是负数。
  • 为什么要加上原来的Local, 因为1,5,3,6, 1到6的距离是5,等于(5-1)+(3-5)+(6-3)

139. Word Break

针对动态规划的思路:

  1. 决定存储什么历史信息以及用什么数据结构来存储
  2. 递推式,就是如何从存储的历史信息中得到当前结果
  3. 初始值的设定
    这道题,dp[i]表示的是在s中的前i-1个字符s[:i]是否存在wordDict里,初始化dp的长度要是s的长度加1,因为要存储dp[0]=True
    双重for循环,注意内层循环时j的范围是for j in range(i, len(s)):, 从i开始到字符串结束。
    判断条件if dp[i] and s[i:j+1] in wordDict: dp[j+1] = True
    dp[i]为真证明s的前i-1个字符存在里边,如果s[i:j+1]也存在,我们就更新dp[j+1]为真
    最后返回dp[-1],d[7] is True because there is "code" in the dictionary that ends at the 7th index of "leetcode" AND d[3] is True

152. Maximum Product Subarray

和maximum sum subarray类似,只不过这道题是求最大乘积。方法也是先初始化maxlocal和res, 但这道题要再加一个minlocal,因为两个很小的负数相乘之后可能会变成很大的整数。所以对nums进行遍历时,递推式里要再加一项对minlocal的更新。
并且要注意因为已经初始化了maxlocal, minlocal, res = nums[0], nums[0], nums[0], 所以for循环要从1开始。
在每次循环过程中:

maxcopy = maxlocal
maxlocal = max(maxlocal*nums[i], nums[i], minlocal*nums[i])
minlocal = min(maxcopy*nums[i], nums[i], minlocal*nums[i])
res = max(maxlocal, res)

要先将maxlocal复制一下,作为计算minloca时使用

62. Unique Paths

具体思路参考第161页https://www.dropbox.com/s/d839bnp9lcroxmq/Sample_Interview_Questions_Set_16.pdf?dl=0

  • 需要注意的是,我们可以用二维数组代替一维数组。只需要对一维数组更新m次就可以。因为在二维数组中,每个方格所拥有的路径数等于上边方格➕左边方格。在一维数组中,每次更新时,当前方格就属于上边方格,所以只需要加上左边方格就可。
  • 还有一点需要注意,内部循环从1开始. 这是因为第一列中每个方格的路径数始终都是1
for i in range(m): 
       for j in range(1, n)```
- 初始化res[0] = 1,res的长度要和n一样!!
#63. Unique Paths II
在上一题的基础上增加了障碍,即有的方格为1时便不可通过。总体思想没有变化,依然可以用一维数组代替二维数组。
- 这次内部循环不能从1开始,因为第一列的方格中有可能存在障碍,即值为1,所以每次循环都要做判断:

if board[i][j] == 1:
res[j] = 0
elif j > 0:
res[j] += res[j-1]

- 依然需要初始化res[0] = 1,res的长度要和n一样!!

#64. Minimum Path Sum
依然是从左上角到右下角,求最短路径和。同样使用一维数组,因为第一行的每个元素只能从左边那个元素过来,所以grid第一行对应的一维数组:

for i in range(1, n):
res[i] = res[i-1] + grid[0][i]

然后对一维数组更新!!m-1次:

for i in range(1, m):
for j in range(n):
if j == 0:
res[j] = res[j] + grid[i][0]
else:
res[j] = min(res[j-1], res[j]) + grid[i][j]

- 当j==0时,证明我们在更新第一列,第一列的元素只能由上边的元素过来,所以是上边元素的值加上当前元素的值,res[j]就是上一行的第一列的元素。
- 当j!=0时,针对每个元素,它可以从上或左的元素得到,我们就在上和左元素中选一个最小值,再加上当前元素。上边的元素就是res[j](因为此时还没有更新res[j]), 左边的元素就是res[j-1]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容