1、确定定义的dp的含义
2、确定递推公式
3、确定dp的初始化
4、确定遍历的顺序
目录
10.14
class Solution {
public int fib(int n) {
if(n==0||n==1) return n;
int a = 0,b = 1,c = 0;
for(int i=2;i<=n;i++){
c = a+b;
a = b;
b = c;
}
return c;
}
}
class Solution {
public int climbStairs(int n) {
if(n==1||n==2) return n;
int[] dp = new int[n+1];
dp[1] = 1;
dp[2] = 2;
for(int i = 3;i<=n;i++)
{
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
}
}
class Solution {
public int minCostClimbingStairs(int[] cost) {
int[] dp = new int[cost.length+1];
dp[0] = dp[1]=0;
for(int i=2;i<cost.length+1;i++){
dp[i] = Math.min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[cost.length];
}
}
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
dp[0][0] = 1;
for(int i = 0;i<m;i++)
for(int j=0;j<n;j++)
{
if(i>0) dp[i][j] +=dp[i-1][j];
if(j>0) dp[i][j] +=dp[i][j-1];
}
return dp[m-1][n-1];
}
}
class Solution {
public int uniquePathsWithObstacles(int[][] Grid) {
int[][] dp = new int[Grid.length][Grid[0].length];
dp[0][0] = 1;
for(int i=0;i<Grid.length;i++)
for(int j=0;j<Grid[0].length;j++){
if(Grid[i][j]==1){
dp[i][j]=0;
continue;
}
if(i>0) dp[i][j]+=dp[i-1][j];
if(j>0) dp[i][j]+=dp[i][j-1];
}
return dp[dp.length-1][dp[0].length-1];
}
}
class Solution {
public int integerBreak(int n) {
int[] dp = new int[n+1];
dp[1] = 1;
dp[2] = 1;
for(int i = 3;i<=n;i++){
for(int j = 1;j<i;j++){
dp[i] = Math.max((i-j)*j,Math.max(dp[i-j]*j,dp[i]));
}
}
return dp[n];
}
}
class Solution {
public int numTrees(int n) {
int[] dp = new int[n+1];
dp[0]=1;
dp[1]=1;
for(int i = 2;i<=n;i++)
for(int j=1;j<=i;j++)
{
dp[i]+=dp[j-1]*dp[i-j];
}
return dp[n];
}
}
10.18
class Solution {
public int rob(int[] nums) {
if(nums.length==1) return nums[0];
int[] dp = new int[nums.length+1];
dp[1] = nums[0];
for(int i = 2;i<=nums.length;i++)
{
dp[i] = Math.max(dp[i-2]+nums[i-1],dp[i-1]);
}
return dp[nums.length];
}
}
class Solution {
public int rob(int[] nums) {
//本题形成了环,导致最后一个和第一不能同时抢,那么采用的策略是遍历两次(实际上一次也行,只是为了更清晰)
//第一次遍历抢1至倒数第二个 第二次遍历抢2至最后的
//然后比较两次最后的结果取大的
if(nums.length==0) return 0;
if(nums.length==1) return nums[0];
int[] dp1 = new int[nums.length+1];
int[] dp2 = new int[nums.length+1];
dp1[1] = nums[0];
dp2[2] = nums[1];
for(int i = 2;i<=nums.length-1;i++){
dp1[i] = Math.max(dp1[i-1],dp1[i-2]+nums[i-1]);
}
for(int i = 3;i<=nums.length;i++){
dp2[i] = Math.max(dp2[i-1],dp2[i-2]+nums[i-1]);
}
return Math.max(dp1[nums.length-1],dp2[nums.length]);
}
}
10.26
背包问题--01背包
class Solution {
public boolean canPartition(int[] nums) {
int sum=0;
for(int a:nums)
sum+=a;
if(sum%2==1) return false;
int size = sum/2;
int[] dp = new int[size+1];
for(int i = 0;i<nums.length;i++)
{
for(int j=size;j>=nums[i];j--)
dp[j] = Math.max(dp[j],dp[j-nums[i]]+nums[i]);
}
if(size==dp[size]) return true;
return false;
}
}
1049. 最后一块石头的重量 II - 力扣(LeetCode)
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for(int a:stones)
sum+=a;
int size = sum/2;
int[] dp = new int[size+1];
for(int i = 0;i<stones.length;i++)
for(int j = size;j>=stones[i];j--)
dp[j] = Math.max(dp[j],dp[j-stones[i]]+stones[i]);
return sum - dp[size]*2;
}
}
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for(int a:nums)
sum+=a;
if((sum+target)%2==1) return 0;
int size = (sum+target)/2;
size = size<0 ? -size:size;
int[] dp = new int[size+1];
dp[0]=1;
for(int i = 0;i<nums.length;i++)
{
for(int j = size;j>=nums[i];j--)
{
dp[j] += dp[j-nums[i]];
}
}
return dp[size];
}
}
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m+1][n+1];
for(String s : strs) {
int zeroNum = 0;
int oneNum = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '0') zeroNum++;
else if (s.charAt(i) == '1') oneNum++;
}
for(int i = m;i >= zeroNum ; i--)
{
for(int j = n;j>= oneNum;j--)
{
dp[i][j] = Math.max(dp[i][j],dp[i-zeroNum][j-oneNum]+1);
}
}
}
return dp[m][n];
}
}