LintCode-动态规划

第一题:经典爬楼梯问题

假设你正在爬楼梯,需要n步你才能到达顶部。但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部?

样例 1:
	输入:  n= 3
	输出: 3
	
	样例解释:
	1) 1, 1, 1
	2) 1, 2
	3) 2, 1
	共3种


样例 2:
	输入:  n = 1
	输出: 1
	
	解释:  
	只有一种方案
public class Solution {
    /**
     * @param n: An integer
     * @return: An integer
     */
    public int climbStairs(int n) {
        int[] dp = new int[1000];
        dp[1] = 1;
        dp[2] = 2;
        for(int i=3;i<=n;i++){
            dp[i] = dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
}

第二题: 最小路径和

给定一个只含非负整数的m*n网格,找到一条从左上角到右下角的可以使数字和最小的路径。

你在同一时间只能向下或者向右移动一步

样例 1:
	输入:  [[1,3,1],[1,5,1],[4,2,1]]
	输出: 7
	
	样例解释:
	路线为: 1 -> 3 -> 1 -> 1 -> 1。


样例 2:
	输入:  [[1,3,2]]
	输出:  6
	
	解释:  
	路线是: 1 -> 3 -> 2

补充知识:如何求二维数组行和列的值? 

int [][] arr = new int[3][4];
System.out.println(arr.length);  //打印出二维数组的行数:3
System.out.println(arr[0].length);   //打印出二维数组的列数:4

arr.length这个经常被我弄错,arr.length打印出的是二维数组的行数,而不是12!

public class Solution {
    /**
     * @param grid: a list of lists of integers
     * @return: An integer, minimizes the sum of all numbers along its path
     */
    public int minPathSum(int[][] grid) {
        if(grid==null||grid[0]==null){
            return -1;
        }
        int m = grid.length;
        int n = grid[0].length;
        int[][] dp = new int[m][n];
        dp[0][0] = grid[0][0];
        for(int i=1;i<n;i++){
            dp[0][i] = dp[0][i-1] + grid[0][i];
        }
        for(int i=1;i<m;i++){
            dp[i][0] = dp[i-1][0] + grid[i][0];
        }
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];
            }
        }
        return dp[m-1][n-1];
    }
}

 优化解法(空间):

public class Solution {
    /**
     * @param grid: a list of lists of integers
     * @return: An integer, minimizes the sum of all numbers along its path
     */
    public int minPathSum(int[][] grid) {
        if(grid==null||grid[0]==null){
            return -1;
        }
        int length = grid[0].length;
        int[] dp = new int[length];
        dp[0] = grid[0][0];
        for(int i=1;i<length;i++){
            dp[i] = dp[i-1]+grid[0][i];
        }
        for(int i=1;i<grid.length;i++){
            dp[0] = dp[0] + grid[i][0];
            for(int j=1;j<length;j++){
                dp[j] = Math.min(dp[j-1],dp[j])+grid[i][j];
            }
        }
        return dp[length-1];
    }
}

第三题:不同的路径 

有一个机器人的位于一个 m × n 个网格左上角。

机器人每一时刻只能向下或者向右移动一步。机器人试图达到网格的右下角。

问有多少条不同的路径?

n和m均不超过100

public class Solution {
    /**
     * @param m: positive integer (1 <= m <= 100)
     * @param n: positive integer (1 <= n <= 100)
     * @return: An integer
     */
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];
        for(int i=0;i<m;i++){
            dp[i][0] = 1;
        }
        for(int i=0;i<n;i++){
            dp[0][i] = 1;
        }
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                dp[i][j] = dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
}

优化解法(空间):

 

public class Solution {
    /**
     * @param m: positive integer (1 <= m <= 100)
     * @param n: positive integer (1 <= n <= 100)
     * @return: An integer
     */
    public int uniquePaths(int m, int n) {
        int[] dp = new int[n];
        for(int i=0;i<n;i++){
            dp[i] = 1;
        }
        for(int j=1;j<m;j++){
            for(int i = 1;i<n;i++){
                dp[i] = dp[i-1]+dp[i];
            }
        }
        return dp[n-1];
    }
}

 第四题:不同的路径II

"不同的路径" 的跟进问题:

现在考虑网格中有障碍物,那样将会有多少条不同的路径?

网格中的障碍和空位置分别用 1 和 0 来表示。

m 和 n 均不超过100

public class Solution {
    /**
     * @param obstacleGrid: A list of lists of integers
     * @return: An integer
     */
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        if(obstacleGrid==null||obstacleGrid[0]==null){
            return -1;
        }
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] dp = new int[m][n];
        if(obstacleGrid[0][0]==0){
            dp[0][0]=1;
        }else{
            return 0;
        }
        for(int i=1;i<m;i++){
            if(obstacleGrid[i][0]==1){
                dp[i][0] = 0;
            }
            else{
                dp[i][0] = dp[i-1][0];
            }
        }
        for(int i=1;i<n;i++){
            if(obstacleGrid[0][i]==1){
                dp[0][i] = 0;
            }
            else{
                dp[0][i] = dp[0][i-1];
            }
        }
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                if(obstacleGrid[i][j]==1){
                    dp[i][j]=0;
                }
                else{
                    dp[i][j] = dp[i-1][j] + dp[i][j-1];
                }
            }
        }
    return dp[m-1][n-1];
    }
}

优化解法(节省空间):

public class Solution {
    /**
     * @param obstacleGrid: A list of lists of integers
     * @return: An integer
     */
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        if(obstacleGrid==null||obstacleGrid[0]==null){
            return -1;
        }
        int n = obstacleGrid[0].length;
        int[] dp = new int[n];
        if(obstacleGrid[0][0]==0){
            dp[0] = 1;
        }else{
            return 0;
        }
        for(int i=1;i<n;i++){
            if(obstacleGrid[0][i]==1){
                dp[i] = 0;
            }else{
                dp[i] = dp[i-1];
            }
        }
        for(int i=1;i<obstacleGrid.length;i++){
           if(obstacleGrid[i][0]==1){
               dp[0] = 0;
           }
           for(int j=1;j<n;j++){
               if(obstacleGrid[i][j]==1){
                   dp[j] = 0;
               }else{
                   dp[j] = dp[j-1]+dp[j];
               }
           }
        }
        return dp[n-1];
    }
}

第五题:数字三角形

给定一个数字三角形,找到从顶部到底部的最小路径和。每一步可以移动到下面一行的相邻数字上。

如果你只用额外空间复杂度O(n)的条件下完成可以获得加分,其中n是数字三角形的总行数。

样例

example 1
Given the following triangle:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

example 2
Given the following triangle:

[
     [2],
    [3,2],
   [6,5,7],
  [4,4,8,1]
]

The minimum path sum from top to bottom is 12 (i.e., 2 + 2 + 7 + 1 = 12).
public class Solution {
    /**
     * @param triangle: a list of lists of integers
     * @return: An integer, minimum path sum
     */
    public int minimumTotal(int[][] triangle) {
        int m = triangle.length;
        int n = triangle[m-1].length;
        for(int i=m-2;i>=0;i--,n--){
            for(int j=0;j<=n-2;j++){
                triangle[i][j] += Math.min(triangle[i+1][j],triangle[i+1][j+1]);
            }
        }
       return triangle[0][0]; 
    }
}

哈哈,我打算从今天开始每天刷5到LintCode上的算法题,在此立下flag!当然啦,作为一个算法上的小菜鸟,我肯定是先从最简单的刷起啦,这样就能一点一点的进步,也有助于我能坚持下去!今天的5道题圆满完成!

今天的算法题是动态规划方面的习题,都是比较简单和基础的,而且还有助于举一反三,找到动态规划的一种节省空间的做法后,我发现这一小类题似乎都可以这样做!

等着明天我再来刷题哟~~~~

最后附上今天拍的美图一张~~~~

 

 

美图

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值