Leetcode:动态规划算法
斐波那契数列
class Solution {public int fib(int n) {if(n == 0 || n <= 1){return n;}int[] dp = new int[n + 1];dp[0] = 0;dp[1] = 1;for(int i = 2; i <= n;i++){dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
}
这道题目让我们求解斐波那契数列算出来的数值。那在这时就需要直到这个的递推公式f(n) = f(n - 1) + f(n - 2)。这时本题的递推公式。首先创建出dp数组,要注意这个初始值(很重要),然后for循环去进行遍历,最终return结果。
动态规划算法:目标和 题号:494
public int findTargetSumWays(int[] nums, int target) {int sum = 0;for(int sums:nums){sum = sum + sums;}//如果target大于sum没有结果if(Math.abs(target) > sum){return 0;}if((sum + target) % 2 == 1){return 0;}int bagSize = (sum + target) / 2;int[] dp = new int[bagSize + 1];dp[0] = 1;for(int i = 0;i < nums.length;i++){for(int j = bagSize ; j >= nums[i];j--){dp[j] = dp[j] + dp[j - nums[i]];}}return dp[bagSize];}
题目的描述是让我们在nums数组中加上+和-使最终的结果相加等于target的值。那就可以使用这样的一个思路。把数组分为两个部分,分为left数组和right数组。left数组存放+的数值,right数组存放-的数值。然后让二者做一个相加得到target。使用sum统计出num数组的值。如果target的值大于sum那sum中的值无论如何进行相加减都达不到这个target的状态。如果target + sum 的值 % 2 有余数的话那就代表无论怎么添加+和-都无法达到target的值。然后创建我们的dp数组。先遍历物品再遍历背包。最后得出结果。
动态规划算法:一和零 题号:474
class Solution {public int findMaxForm(String[] strs, int m, int n) {if(strs == null || strs.length == 0){return 0;}int[][] dp = new int[m + 1][n + 1];dp[0][0] = 0;for(String str : strs){int x = 0;int y = 0;for(char s : str.toCharArray()){if(s == '0')x++;elsey++;}for(int i = m;i >= x;i--){for(int j = n; j >= y;j--){dp[i][j] = Math.max(dp[i][j],dp[i - x][j - y] + 1);}}}return dp[m][n];}
}
题目给了我们一个数组和m和n,要求返回的结果里面的元素包含m个0和n个1。返回元素的数量,这里可以用dp数组来实现这个思路dp数组代表我们的背包,不断的向背包中放入元素。直到达到满足的条件。具体的实现用for循环遍历数组再遍历数组中的元素,统计0和1的数量。最后用两层for循环控制这个0和1的数量即可。
完全背包问题:组合总和lV 题号:377
public int combinationSum4(int[] nums, int target) {if(nums == null || nums.length == 0){return 0;}//定义dp数组int[] dp = new int[target + 1];//初始化dp数组dp[0] = 1;//先遍历背包后遍历物品for(int j = 0;j <= target;j++){for(int i = 0;i < nums.length;i++){if(j >= nums[i]){ //背包大于物品dp[j] = dp[j] + dp[j - nums[i]];} }}return dp[target];}
首先拿到一个 数组和一个目标数字。要求在数组中找到哪几个数组相加等于target。这里采用dp数组的思路。明确dp数组的含义:dp[j] 代表容量为j的背包最多可以容纳dp[j]的元素。然后再进行dp数组的初始化。dp[0] = 1容量为0的背包进行一次装入。采用先遍历背包再遍历数组方式,最后写入递推公式。
完全背包问题:零钱兑换 题号:322
public int coinChange(int[] coins, int amount) {if(coins == null || coins.length == 0){return -1;}int max = Integer.MAX_VALUE;int[] dp = new int[amount + 1];//将数组初始化为最大值for(int i = 0;i < dp.length;i++){dp[i] = max;}dp[0] = 0;for(int i = 0;i < coins.length;i++){ //先物品再背包for(int j = coins[i] ;j <= amount;j++){if(dp[j - coins[i]] != max){dp[j] = Math.min(dp[j],dp[j - coins[i]] + 1);}}}return dp[amount] == max ? -1 : dp[amount];}
拿到一个硬币数组和一个amount的值,要求在数组中找到硬币的和相加等于amount。这道题目与上一体相类似,还是采用dp数组的思路。创建dp数组并将数组初始化为最大值,那为什么初始化为最大值呢,如果不初始化为最大值。后续会发生比数组中的值更小覆盖的情况。因为我们这道题求得是最少硬币个数,这也是区别最大的地方。采用的是先遍历物品再遍历背包的情况。从dp中获取最小值