内容简介:摘要:本周我利用休息时间刷了两道简单、一道中等的动态规划算法题目,和大家一起分享一下,作为动态规划算法专题的开始。我的主页https://qupzhi.com ,转载请注明出处。三要素
摘要:本周我利用休息时间刷了两道简单、一道中等的动态规划算法题目,和大家一起分享一下,作为动态规划算法专题的开始。
我的主页https://qupzhi.com ,转载请注明出处。
- 以下内容用 go 语言实现
动态规划三要素
三要素
- 最优子结构性质,通俗的说法就是问题的最优解包含其子问题的最优解
- 边界
- 状态转移方程
重复求区间和
给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。 示例: 给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange() sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0, 5) -> -3 说明: 你可以假设数组不可变。 会多次调用 sumRange 方法。
三种思路:
- 直接根据每次传进来的区间进行现场计算
- 用一个Map,把每次传进来的区间拼成一个key,二次查询的时候就有了缓存
- 直接用一个1D的数组,每个元素存0到当前值之间的和,这样区间和就是两个下标存元素相减就可以了
type NumArray struct { } var sum *[]int func Constructor(nums []int) NumArray { var obj NumArray for k, v := range nums { if k > 0 { nums[k] = nums[k-1] + v } } sum = &nums return obj } func (this *NumArray) SumRange(i int, j int) int { if i == 0 { return (*sum)[j] } return (*sum)[j] - (*sum)[i-1] } func Test(){ arr := []int{1,2,3,4} obj := Constructor(arr) res := obj.SumRange(0,3) fmt.Println(res) }
经典问题爬楼梯
假设你正在爬楼梯。需要 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 阶
因为每次都可以分解为1步和2步,边界就是1步2步,状态转移方程就是 f(n) = f(n-1) + f(n-2) (n>=3)
,这里提供三种思路
- 递归
- 字典
- 动态规划,每次都用前一次的值推倒后一次的答案
// f(n) = f(n-1) + f(n-2) (n>=3) // f(1) = 1 // f(2) = 2 // 方法一、递归 func climbStairs1(n int)int{ if n < 0 { return 0 } if n == 1 { return 1 } if n == 2 { return 2 } return climbStairs1(n-1) + climbStairs1(n-2) } //方法二、动归 func climbStairs(n int) int { if n == 1 { return 1 } if n == 2 { return 2 } res,a,b := 0,1 ,2 for i:=3;i<=n;i++{ res = a + b a = b b = res } return res } func Test1(){ fmt.Println(climbStairs1(10)) } func Test2(){ fmt.Println(climbStairs(100)) }
最大正方形面积
221. Maximal Square Medium 1165 29 Favorite Share Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area. Example: Input: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 Output: 4
三种思路:
-
方法一 逐渐增加连续的 ‘1’ 的长度 ,然后用一个函数去看是否构成正方形,构成的话就继续增加边长,直到找到最大的正方形为止
时间复杂 O((mn)^2) 空间 O(1)
-
方法二 用一个二维数组的的每个元素都来保存边长
每次只要遍历到的点是1,就开始取他的上、左、左上三个值取最小,再加1得到当前点的值
dp[x,y] = min(min(dp[x-1][y],dp[x][y-1]) , dp[x-1][y-1])+1 O(mn) O(mn)
-
方法三
input [1,1,0][1,1,0] 0000 0110 0120
- 每次遍历总是要知道上一行的数据,所以至少得保留一行
- 可以发现,遍历到第三行的时候,第一行已经没有用了!
- 每次遍历的时候,假设只保留上一行,比如在第三行,每次走一位,我们要更新当前值,当前位置的马上的覆盖值对于下一次来说就是左上角的值(2*2)
- 对于这一次来说就是上,因为当前位置的左边已经更新了所以就是左,那我们当前就出现了左、上、左上三个值了,凑够了。
-
初始化就全0,prev=0
dp[y]=min(dp[y-1],dp[y],prev) O(mn) O(m)
// 方法二 func maximalSquare(matrix [][]byte) int { rows := len(matrix) cols := 0 if rows>0{ cols = len(matrix[0]) }else{ cols = 0 } dp := make([][]int,rows+1) for i:=0;i < len(dp);i++{ dp[i] = make([]int,cols+1) } maxlen := 0 for x:=1;x <= rows; x++{ for y:=1;y <= cols;y++{ if matrix[x-1][y-1] == '1'{ tmp := min(min(dp[x-1][y],dp[x][y-1]),dp[x-1][y-1])+1 dp[x][y]=tmp maxlen = max(maxlen,tmp) } } } return maxlen * maxlen } // 方法三 func maximalSquare2(matrix [][]byte) int { rows := len(matrix) cols := 0 if rows>0{ cols = len(matrix[0]) }else{ cols = 0 } dp := make([]int,cols +1) maxlen,prev := 0,0 for x:=1;x <= rows; x++{ for y:=1;y <= cols;y++{ tmp := dp[y] //当前值当下一次的prev if matrix[x-1][y-1] == '1'{ dp[y] = min(min(dp[y],dp[y-1]),prev) + 1 //分别对应上,左,左上 maxlen = max(dp[y],maxlen) }else{ dp[y] = 0 } prev = tmp } } return maxlen * maxlen } func Test1(){ t1 :=[][]byte{{'1','0','1','0','0'},{'1','0','1','1','1'},{'1','1','1','1','1'},{'1','0','0','1','0'}} t2 :=[][]byte{} fmt.Println(maximalSquare(t2)) fmt.Println(maximalSquare2(t1)) } func min(x, y int) int { if x < y { return x } return y } func max(x, y int) int { if x > y { return x } return y }
以上所述就是小编给大家介绍的《一起刷算法_动态规划01》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。