动态规划小白总结

**动态规划 --小白学习之路
(强调:我就是个新手,我就是个弟弟,代码写的比较烂大佬们别骂我)
题目分类:
1.最值问题(理解为比较题)
2.数量问题(理解为加法题)
3.存在性问题(理解为判断题)
4.以上都是小弟自己瞎总结,大佬们别骂
解题思路:
将大问题分为一个个等价的子问题
题目(最值问题):
力扣剑指offer 42 .连续子数组的最大和
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
思路:最值问题可以理解为比较类型的问题,当我们需要找到当前数组的最大和,那么只有两种方法可以到达当前数组元素,
1.当前元素的前一个元素加上当前元素总和变得更大,则取当前数组和前一个数组的和。
2.反之,取当前元素为唯一元素 。
分割子问题为: fn[i] = Math.max(fn[i - 1] + nums[i], nums[i]);
那么只需要遍历一次即可得到最大的和

class Solution {
    public int maxSubArray(int[] nums) {
        int max = nums[0];
        int [] fn = new int[nums.length];
        fn[0] = nums[0];
        for(int i = 1; i < nums.length; i++) {
            fn[i] = 0;
            fn[i] = Math.max(fn[i - 1] + nums[i], nums[i]);
            max = Math.max(fn[i] , max);
        }
        return max;
    }
}

力扣322零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。
思路:和上一题一样,目前只有coins里面的钱币的金额才能到达amount,那么到达amount的方式只有

for(int i = 0; i < coins.length; i++) {
	amount - coins[i] //这些
}
//换示例来说: 假如coins中有1,2,5面值的钱币,那么到达最终amount的前一步只能是amount - 1 , amount - 2 ,amount - 5这三种方式

那么分割为子问题式子为:

  for(j = 0; j < n; j++) {
           if(i >= coins[j] && f[i - coins[j]] != Integer.MAX_VALUE)
           f[i] = Math.min(f[i - coins[j]] + 1, f[i]);
   }

完整代码为:

class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] f = new int [amount + 1] ;
        int n = coins.length;
        f[0] = 0;
        int i , j;
        for(i = 1; i <= amount; i++) {
            f[i] = Integer.MAX_VALUE;
            for(j = 0; j < n; j++) {
                if(i >= coins[j] && f[i - coins[j]] != Integer.MAX_VALUE)
                f[i] = Math.min(f[i - coins[j]] + 1, f[i]);
            }
        }
        if(f[amount] == Integer.MAX_VALUE) return -1;
        else return f[amount];
    }
}

题目(数量问题)
力扣62不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?
在这里插入图片描述
思路:我们到达最右下角,只有他的上面和他的左边才能到达,那么分割子问题为:想要知道到达当前的点的上面到达的方法和左边到达的方法即可
完整的代码为

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] f = new int[m][n];
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(i == 0 || j == 0) f[i][j] = 1;
                else {
                    f[i][j] = f[i - 1][j] + f[i][j - 1];  //加减法问题
                }
            }
        }
        return f[m - 1][n - 1];
    }
}

力扣 70 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

思路:假如向跳到当前的楼梯,那么你只有两种方法,你可以从比当前 台阶少一个的台阶跳上来,也可以从当前台阶少两个台阶的地方跳上来,是不是似曾相识的感觉哈哈哈哈
完整代码:

class Solution {
    public int climbStairs(int n) {
        int []fn = new int[n + 1];
        fn[0] = 1;
        fn[1] = 1;
        for(int i = 2; i <= n; i++) {
            fn[i] = fn[i - 1] + fn[i - 2];
        }
        return fn[n];
    }
}

题目(存在性问题)
力扣55 跳跃游戏
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

思路:这题其实用动态规划太慢了,自己体会把嘿嘿

class Solution {
    public boolean canJump(int[] nums) {
        boolean [] f = new boolean[nums.length];
        f[0] = true;
        for(int i = 1; i < nums.length; i++) {
            f[i] = false;
            for(int j = 0; j < i; j++) {
                if(f[j] == true && i - j<= nums[j]) {
                    f[i] = true;
                    break;
                }
            }
        }
        return f[nums.length - 1];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值