专题6--动态规划
1、动态规划基础知识
什么情况下可能是动态规划?满足下面三个条件之一:
1. Maximum/Minimum -- 最大最小,最长,最短;写程序一般有max/min。
2. Yes/No----是否可行;写程序一般有||。
3. Count(*)--数方案的个数,比如有多少条路径这种。初始化0个的情况下,初始化为1,联想组合数学里面0! = 1。
则 “极有可能”是使用动态规划求解。
什么情况下可能不是动态规划?
1)如果题目需要求出所有 “具体 ”的方案而非方案 “个数 ”;
2)输入数据是一个 “集合 ”而不是 “序列 ”。(区分就是调整元素顺序看是否对求解有影响)
动态规划的4点要素:
1) 状态 State
灵感,创造力,存储小规模问题的结果
a) 最优解/Maximum/Minimum
b) Yes/No
c) Count(*)
2) 方程 Function
状态之间的联系,怎么通过小的状态,来求得大的状态
3) 初始化 Intialization
最极限的小状态是什么, 起点
4) 答案 Answer
最大的那个状态是什么,终点
动态规划有四类:
1. Matrix DP (15%)
2. Sequence (40%)
3. Two Sequences DP (40%)
*4. Others (5%)
动态规划就是 *解决了重复计算 * 的搜索。
动态规划的实现方式:
1. 记忆化搜索;
2. 循环。
循环求解更 *正规 *,存在空间优化的可能,大多数面试官可以接受;(滚动数组)
记忆化搜索空间耗费更大,但思维难度小,编程难度小,时间效率很多情况下更高,少数有 *水平 *的面试官可以接受。
动态规划时间复杂度分析就是看有几个for循环。
3、Matrix DP
state: f[x][y] 表示我从起点走到坐标 x,y……
function: 研究走到 x,y这 个点之前的一步
intialize: 起点
answer: 终点
小技巧:intialize: f[0][0] = A[0][0]
// f[i][0] = sum(0,0 -> i,0)
// f[0][i] = sum(0,0 -> 0,i)
初始化的时候需要初始化f[i][0] ,f[0][i] ,这样可以在i-1的时候避免边界检查。
3.1、120. Triangle
https://leetcode.com/problems/triangle/#/description
找到和最小的一条路径。
思路:
1)记忆化搜索memorize+ divide and conquer
class Solution { public: int helper(int x,int y,int size,vector<vector<int>>& triangle,vector<vector<int>>& minSum){ if(x >= size){ return 0; } if(minSum[x][y] != INT_MAX){ return minSum[x][y]; } minSum[x][y] = min(helper(x + 1,y, size,triangle,minSum), helper(x + 1,y + 1,size,triangle,minSum)) + triangle[x][y]; return minSum[x][y]; } int minimumTotal(vector<vector<int>>& triangle) { if(triangle.size() == 0 || triangle[0].size() == 0){ return -1; } int row = triangle.size(); int col = triangle[row - 1].size(); vector<vector<int>> minSum(row,vector<int> (col,INT_MAX)); return helper(0,0,triangle.size(),triangle,minSum); } };