leetcode 19

在这里插入图片描述

暴力递归

import java.util.ArrayList;
import java.util.List;

public class SplitNumber2 {

    public static int ways1(int n){
        if(n < 1){
            return 0;
        }
        return process(1,n);
    }

    public static int process(int pre,int rest){
        if(rest == 0){
            return 1;
        }
        if(pre > rest){
            return 0;
        }
        
        int ways = 0;
        for(int i = pre;i <= rest;i++){
            ways += process(i,rest-i);
        }
        return ways;
    }
}

dp

   public static int way2(int n){
        int[][] dp = new int[n+1][n+1];

        for(int pre = 1;pre <= n;pre++){
            dp[pre][0] = 1;
        }

        for(int pre = n;pre>=1;pre--){
            for(int rest = pre;rest<=n;rest++){
                int way = 0;
                for(int i = pre;i <= rest;i++){
                    way += dp[i][rest-i];
                }
                dp[pre][rest] = way;
            }
        }
        
        return dp[1][n];
    }

可以画图找规律 优化
在这里插入图片描述
dp[i][j] dp[n][k]
dp[7][3]的第一种可能性是dp[6][3] 这种情况就是把7放在最后
依赖dp[6][2] 这种情况把7放在倒数第二位
依赖dp[6][1] 这种情况把7放在导数第三位
依赖dp[6][0] 这种情况把7放在导数第四位

dp[6][7] 不依赖dp[6][0] 会存在截掉一部分的情况
行列模型 关注开头和结尾

public class KInversePairs2 {
    public static int dp(int N,int K){
        if(N < 1 || K < 0){//可以加一个判断上限的,因为逆序数有上限的 对于一个固定的数
            return 0;
        }
        if(K == 0){
            return 1;
        }

        int[][] dp = new int[N+1][K+1];

        dp[1][0] = 1;
        for(int i = 2;i <= N;i++){
            dp[i][0] = 1;
        }
        for(int i = 2;i <= N;i++){
            for(int j = 1;j<=K;j++){
                //视频讲的这个地方可能笔误了
                //dp[i][j] i < j dp[i-1][j...0]
                //dp[i][j] i >= j dp[i-1][j-i+1]
                //以上两种情况合在一起
                //突然顿悟 ,比如dp[7][3] 为什么依赖dp[6][2]
                // 这个是把7放在倒数第二个位置 为1种逆序对,
                //然后dp[6][2]为原本的2种逆序对。组合在一起构成了dp[7][3]的三种逆序对
                for(int s=  j; s>= Math.max(0,j-i+1);s--){
                    dp[i][j] += dp[i-1][s];
                }
                //下面的代码为优化后的。可以通过计算得出下面规律
                /*
                if(i > j){
                    dp[i][j] = dp[i][j-1] + dp[i-1][j];
                }
                if(i <= j){
                    dp[i][j]  = dp[i-][j-1] + dp[i][j-1] - dp[i-1][j-1];
                }
                //也可简写为
                dp[i][j] = dp[i][j-1] + dp[i-1][j] -(i <=j ? dp[i-1][j-1] : 0);
                 */
            }
        }
        return dp[N][K];
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值