leetcode动态规划笔记二
动态规划
题目分类
矩阵型DP
- Unique Paths II : 矩阵型DP,求所有方法总数
- Minimum Path Sum:矩阵型,求最大最小值
- Triangle : 矩阵型,求最大最小值
- Maximum Square :矩阵型,求最大最小值
- Range Sum Query 2D - Immutable : 求和
Unique Paths II : 矩阵型DP,求所有方法总数
方法一:自顶向下
递归法,time limited
class Solution {
    int helper(int[][] g, int x, int y){
        int top = 0, left = 0;
        if(g[x][y] == 1) return 0;
        if(x == 0 && y == 0) return 1;
        if(x > 0){
            top = helper(g, x - 1, y);
        }
        if(y > 0){
            left = helper(g, x, y - 1);
        }
        return top + left;
    }
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        return helper(obstacleGrid, obstacleGrid.length - 1, obstacleGrid[0].length -1);
    }
}
方法一:自顶向下
递归法 + memo ac
class Solution {
    Map<Long, Integer> m = new HashMap<>();
    int helper(int[][] g, int x, int y){
        int top = 0, left = 0;
        if(g[x][y] == 1) return 0;
        if(x == 0 && y == 0) return 1;
        long key = ((long)x) << 32 | y; // long key = x << 32 | y; 错误
        if(m.containsKey(key)) return m.get(key);
        if(x > 0){
            top = helper(g, x - 1, y);
        }
        if(y > 0){
            left = helper(g, x, y - 1);
        }
        m.put(key, top + left);
        return top + left;
    }
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        return helper(obstacleGrid, obstacleGrid.length - 1, obstacleGrid[0].length -1);
    }
}
方法三:自底向上
递推 + memo
这里用了二维memo,其实状态转移中,当前step只与上一step有关系,只用一维memo就可以了。
class Solution {
    public int uniquePathsWithObstacles(int[][] g) {
        if(g.length == 0) return 0;
        int[][] ps = new int[g.length][g[0].length];
        boolean obstacle = false;
        for(int i = 0; i < g.length; i ++){
            if(g[i][0] == 1){
                obstacle = true;
            }
            ps[i][0] = obstacle ? 0 : 1;
        }
        obstacle = false;
        for(int i = 0; i < g[0].length; i ++){
            if(g[0][i] == 1){
                obstacle = true;
            }
            ps[0][i] = obstacle ? 0 : 1;
        }        
        for(int i = 1; i < g.length; i++){
            for(int j = 1; j < g[0].length; j++){
                if(g[i][j] == 1){
                    ps[i][j] = 0;
                }
                else{
                    ps[i][j] = ps[i-1][j] + ps[i][j-1];
                }
            }
        }
        return ps[g.length-1][g[0].length-1];
    }
}
Minimum Path Sum:矩阵型,求最大最小值
方法一:自底向上 + 二维memo
class Solution {
    public int minPathSum(int[][] g) {
        if (g.length == 0) return 0;
        int[][] sum = new int[g.length][g[0].length];
        sum[0][0] = g[0][0];
        for(int i = 1; i < g.length; i++){
            sum[i][0] = g[i][0] + sum[i-1][0];
        }
        for(int i = 1; i < g[0].length; i++){
            sum[0][i] = g[0][i] + sum[0][i-1];
        }        
        for(int i = 1; i < g.length; i ++){
            for(int j = 1; j < g[0].length; j++){
                sum[i][j] = g[i][j] + Math.min(sum[i-1][j], sum[i][j-1]);
            }
        }
        return sum[g.length-1][g[0].length-1];
    }
}
方法二:自底向上 + 一维memo
class Solution {
    public int minPathSum(int[][] g) {
        if (g.length == 0) return 0;
        int[] sum = new int[g[0].length];
        sum[0] = g[0][0];
        for(int i = 1; i < g[0].length; i++){
            sum[i] = g[0][i] + sum[i-1];
        }        
        for(int i = 1; i < g.length; i ++){
            sum[0] = sum[0] + g[i][0];
            for(int j = 1; j < g[0].length; j++){
                sum[j] = g[i][j] + Math.min(sum[j], sum[j-1]);
            }
        }
        return sum[g[0].length-1];
    }
}
Triangle : 矩阵型,求最小值
方法一 : 自定向下
递归 + memo
问题拆分、状态、状态转移方程、初始值,一个都不能少
class Solution {
    Map<Long, Integer> m = new HashMap<>();
    int helper(List<List<Integer>> tri, int row, int col){
        long key = (long)row << 32 | col;
        if(m.containsKey(key)){
            return m.get(key);
        }
        if ( row == 0 && col == 0 ){  //不能忽略此逻辑
            return tri.get(0).get(0);
        }
        int left = Integer.MAX_VALUE;
        int top = Integer.MAX_VALUE;
        if(row > 0){
            if(col < tri.get(row).size() - 1){
                top = helper(tri, row - 1, col);
            }
            if(col > 0){
                left = helper(tri, row - 1, col - 1);
            }
        }
        int val = Math.min(top, left) + tri.get(row).get(col);
        m.put(key, val);
        return val;
    }
    public int minimumTotal(List<List<Integer>> tri) {
        if(tri.size() == 0) return 0;
        int sum = Integer.MAX_VALUE;
        for(int j = 0; j < tri.get(tri.size()-1).size(); j++){
            sum = Math.min(sum, helper(tri, tri.size()-1, j));
        }
        return sum;
    }
}
方法二 : 自底向上
递推 + memo,下面的方法还可以进一步优化
class Solution {
    public int minimumTotal(List<List<Integer>> tri) {
        if(tri.size() == 0) return 0;
        int[] memo = new int[tri.get(tri.size()-1).size()];
        memo[0] = tri.get(0).get(0);
        for(int i = 1; i < tri.size(); i ++){
            for(int j = tri.get(i).size() -1; j >= 0 ; j--){
                if(j == 0){
                    memo[j] = memo[j] + tri.get(i).get(j);
                }
                else if(j == tri.get(i).size() - 1){
                    memo[j] = memo[j-1] + tri.get(i).get(j);
                }
                else{
                    memo[j] = Math.min(memo[j-1], memo[j]) + tri.get(i).get(j);
                }
            }
        }
        int sum = Integer.MAX_VALUE;
        for(int i=0; i<memo.length; i++){
            sum = Math.min(sum, memo[i]);
        }
        return sum;
    }
}
Maximum Square :矩阵型,求最大最小值
方法一:自底向上
递推 + memo
主要看斜对角线,当前位置能成为多大square,要看左上角位置有多大square。本地弯弯道道挺多。
class Solution {
    public int maximalSquare(char[][] m) {
        if(m.length == 0) return 0;
        int[][] memo = new int[m.length + 1][m[0].length + 1];
        for(int i = 0; i <= m.length; i++ ){
            memo[i][0] = 0;
        }
        for(int i = 0; i <= m[0].length; i++){
            memo[0][i] = 0;
        }
        int maxi = 0;
        for(int i = 0; i < m.length; i++){
            for(int j = 0; j < m[0].length; j++){
                if(m[i][j] != '1'){
                    memo[i+1][j+1] = 0;
                    continue;
                }
                if(memo[i][j] <= 0){
                    memo[i+1][j+1] = 1;
                }
                else {
                    int k = 1;
                    for(; k <= memo[i][j]; k++){
                        if(m[i-k][j] != '1' || m[i][j-k] != '1'){
                            break;
                        }
                    }
                    memo[i+1][j+1] = k;
                }
                //System.out.println("i" + i + " j" + j + " =" + memo[i+1][j+1]);
                maxi = Math.max(memo[i+1][j+1], maxi);
            }
        }
        return maxi * maxi;
    }
}
Range Sum Query 2D - Immutable
方法一 : 自底向上, 递推 + memo
class NumMatrix {
    private int[][] memo;
    public NumMatrix(int[][] m) {
        if(m.length == 0 || m[0].length == 0) return;
        memo = new int[m.length][m[0].length + 1];
        for(int i = 0; i < m.length; i++){
            for(int j = 0; j < m[0].length; j++){
                memo[i][j+1] = memo[i][j] + m[i][j];
            }
        }
    }
    public int sumRegion(int row1, int col1, int row2, int col2) {
        int sum = 0;
        for(int i = row1; i <= row2; i++){
            sum += (memo[i][col2+1] - memo[i][col1]);
        }
        return sum;
    }
}
leetcode动态规划笔记二的更多相关文章
- leetcode动态规划笔记一---一维DP
		动态规划 刷题方法 告别动态规划,连刷 40 道题,我总结了这些套路,看不懂你打我 - 知乎 北美算法面试的题目分类,按类型和规律刷题 题目分类 一维dp House Robber : 求最大最小值 ... 
- leetcode动态规划笔记三---单序列型
		单序列型DP 相比一维DP,这种类型状态转移与过去每个阶段的状态都有关. Longest Increasing Subsequence : 求最大最小值 Perfect Squares : 求某个规模 ... 
- 快速上手leetcode动态规划题
		快速上手leetcode动态规划题 我现在是初学的状态,在此来记录我的刷题过程,便于以后复习巩固. 我leetcode从动态规划开始刷,语言用的java. 一.了解动态规划 我上网查了一下动态规划,了 ... 
- 《CMake实践》笔记二:INSTALL/CMAKE_INSTALL_PREFIX
		<CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ... 
- jQuery源码笔记(二):定义了一些变量和函数 jQuery = function(){}
		笔记(二)也分为三部分: 一. 介绍: 注释说明:v2.0.3版本.Sizzle选择器.MIT软件许可注释中的#的信息索引.查询地址(英文版)匿名函数自执行:window参数及undefined参数意 ... 
- Mastering Web Application Development with AngularJS 读书笔记(二)
		第一章笔记 (二) 一.scopes的层级和事件系统(the eventing system) 在层级中管理的scopes可以被用做事件总线.AngularJS 允许我们去传播已经命名的事件用一种有效 ... 
- Python 学习笔记二
		笔记二 :print 以及基本文件操作 笔记一已取消置顶链接地址 http://www.cnblogs.com/dzzy/p/5140899.html 暑假只是快速过了一遍python ,现在起开始仔 ... 
- WPF的Binding学习笔记(二)
		原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ... 
- webpy使用笔记(二) session/sessionid的使用
		webpy使用笔记(二) session的使用 webpy使用系列之session的使用,虽然工作中使用的是django,但是自己并不喜欢那种大而全的东西~什么都给你准备好了,自己好像一个机器人一样赶 ... 
随机推荐
- ssh配置连接远程主机 彻底解放你的双手
			查看ssh支持配置 man ssh_config 打开ssh并配置 vi ~/.ssh/config 基本配置示例说明 密钥文件连接 Host <别名> Port <机器端口号> ... 
- 分布式系统CAP定理与BASE理论
			CAP定理: 一个分布式系统不可能同时满足一致性(C:Consistency).可用性(A:Availability)和分区容错性(P:Partition tolerance)这三个基本要求,最多只能 ... 
- GitBook   github
			创建一个新的仓库 创建一个新文件,名为SUMMARY.md 创建一本书首先进入gitbook的官网:https://www.gitbook.com/ 创建账户https://github.com/ 在 ... 
- MVC框架模式和Javaweb经典三层架构
			一.MVC设计模式 1.MVC的概念 首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(Vie ... 
- SQLSERVER|CDC日志变更捕获机制
			一.什么是CDC? 变更数据捕获(Change Data Capture ,简称 CDC)记录 SQL Server 表的插入.更新和删除活动.SQLServer的操作会写日志,这也是CDC捕获数据的 ... 
- webpack4.0构建项目流程
			webpack4.0构建项目流程,具体的就不一一唠叨了,这里给出构建流程步骤: 流程大图: 下载高清大图 
- 刷题记录:[强网杯 2019]Upload
			目录 刷题记录:[强网杯 2019]Upload 一.知识点 1.源码泄露 2.php反序列化 刷题记录:[强网杯 2019]Upload 题目复现链接:https://buuoj.cn/challe ... 
- ubuntu之路——day18 用pytorch完成CNN
			本次作业:Andrew Ng的CNN的搭建卷积神经网络模型以及应用(1&2)作业目录参考这位博主的整理:https://blog.csdn.net/u013733326/article/det ... 
- elasticsearch-py 解决 too_long_frame_exception 问题
			elasticsearch-py 解决 too_long_frame_exception 问题 老大让我搞一搞数据统计,配环境时遇到个奇葩错误,记录一下,希望能帮助到某些人. 我需要安装 Elasti ... 
- [web]   前端一些细节
			作者:水落斜阳链接:https://www.jianshu.com/p/7a8124fdf945来源:简书著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 1, reflow和re ... 
