-
Notifications
You must be signed in to change notification settings - Fork 305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Day 17 | 8/25 #27
Comments
Leetcode70 Climbing Stairs
这道题作为DP的启蒙题(拥有非常明显的重叠子结构),我在这详细的讲一讲LC大神们的答案是如何从一个毫无优化的做法,效率极低的递归解法,慢慢的进化到他们现在的答案,也给不会DP思路的同学补一补基础。 Top-Down这道题自顶向下的思考:如果要爬到
继续向下延伸思考,
之后对返回子问题之和即可。 具体可以看下图。 根据以上的思路得到下面的代码 Solution 1: Recursion (TLE)class Solution(object):
def climbStairs(self, n):
if n == 1: return 1
if n == 2: return 2
return self.climbStairs(n - 1) + self.climbStairs(n - 2) TLE原因:以上代码实现之所以会TLE,是因为递归的时候出现了很多次重复的运算。就如上图显示的爬 优化思路:这时候的思路为:如果能够将之前的计算好了的结果存起来,之后如果遇到重复计算直接调用结果,效率将会从之前的 实现方法:有了思路,实现方面则开辟一个长度为N的数组,将其中的值全部赋值成 Solution 2: Top-Down (using array)class Solution(object):
def climbStairs(self, n):
if n == 1: return 1
res = [-1 for i in range(n)]
res[0], res[1] = 1, 2
return self.dp(n-1, res)
def dp(self, n, res):
if res[n] == -1:
res[n] = self.dp(n - 1, res) + self.dp(n - 2, res)
return res[n]
这样是不是还是很抽象?我们可以举个例子,当
大家看到了,我们先从第 这就是Top-Down的思路,从大化小,思路就和DFS Tree中的分制一样。 Bottom-UpBottom-Up的思路则相反。我们不从 当我们有了第1层和第2层的base case,我们则可以直接从base case向上推得第3层,第4层以及第n层的答案,具体实现如下: Solution 3: Bottom-Up (using array)class Solution(object):
def climbStairs(self, n):
if n == 1: return 1
res = [0 for i in range(n)]
res[0], res[1] = 1, 2
for i in range(2, n):
res[i] = res[i-1] + res[i-2]
return res[-1] 这种方法的使用的时候,我们发现其实在每一次更新当前的数的时候,我们最终返回的是最后一次更新的数,而我们的 Solution 3: Bottom-Up (Constant Space)class Solution(object):
def climbStairs(self, n):
if n == 1: return 1
a, b = 1, 2
for _ in range(2, n):
a, b = b, a + b
return b 198 House Robber
class Solution(object):
def rob(self, nums):
if not nums: return 0
if len(nums) <= 2: return max(nums)
res = [0] * len(nums)
res[0], res[1] = nums[0], max(nums[0], nums[1])
for i in range(2, len(nums)):
res[i] = max(res[i-1], res[i-2] + nums[i])
return res[-1] 以上的代码需要O(N)空间,利用滚动数组可以实现O(1)空间: class Solution(object):
def rob(self, nums):
if not nums: return 0
if len(nums) <= 2: return max(nums)
res = [0] * 2
res[0], res[1] = nums[0], max(nums[0], nums[1])
for i in range(2, len(nums)):
res[i%2] = max(res[(i-1)%2], res[(i-2)%2] + nums[i])
return max(res[0], res[1]) 213. House Robber II
这道题相对于House Robber I里面要解决的edge就是circle的头和尾不能为邻居,那我们只需要在之前写好的代码基础上计算两个区间即可,第一个区间是nums[1:], 第二个区间是nums[:-1],在比较这两个区间哪个大即可。 如上面的例图,对于 class Solution(object):
def rob(self, nums):
if not nums: return 0
if len(nums) <= 2: return max(nums)
return max(self.rob_row(nums[1:]), self.rob_row(nums[:-1]))
def rob_row(self, nums):
res = [0] * len(nums)
res[0], res[1] = nums[0], max(nums[0], nums[1])
for i in range(2, len(nums)):
res[i] = max(res[i-1], res[i-2] + nums[i])
return res[-1] 滚动数组优化class Solution(object):
def rob(self, nums):
if not nums: return 0
if len(nums) <= 2: return max(nums)
return max(self.rob_row(nums[1:]), self.rob_row(nums[:-1]))
def rob_row(self, nums):
res = [0] * 2
res[0], res[1] = nums[0], max(nums[0], nums[1])
for i in range(2, len(nums)):
res[i%2] = max(res[(i-1)%2], res[(i-2)%2] + nums[i])
return max(res[0], res[1]) 221 Maximum Square
class Solution(object):
def maximalSquare(self, matrix):
if not matrix: return 0
m , n = len(matrix), len(matrix[0])
dp = [[ 0 if matrix[i][j] == '0' else 1 for j in range(0, n)] for i in range(0, m)]
for i in range(1, m):
for j in range(1, n):
if matrix[i][j] == '1':
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
else:
dp[i][j] = 0
res = max(max(row) for row in dp)
return res ** 2 300 Longest Increacing Sequence
class Solution:
def lengthOfLIS(self, nums):
if not nums: return 0
dp = [1] * len(nums)
for i in range(len(nums)):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
|
今日计划 | DP基础
The text was updated successfully, but these errors were encountered: