《Leetcode每日一题》629.K个逆序对数组

 关键:

dp[i][j]表示从0-i中选,逆序对数量为j的集合

新增加一个i,那么他最多会增加i-1个逆序对,最少会增加0个,然后枚举一下。

[start, x, x, x, x, ..., x],start可以为 1 到 n 中的任意一个数,
故以start为起始的第一个数字,一共有n种可能:

设 f(n, k) 表示 1 到 n 组成的数组产生k个逆序对的数组个数。

start = 1 时, [1, x, x, ..., x], 第一个数字 1 和后面的 n - 1 个
数字都不会产生逆序对,因此后面 n - 1 个数必须要产生 k 个
逆序对,故f(n, k) = f(n - 1, k);

start = 2 时, [2, x, x, ..., x], 第一个数字 2 和后面的 n - 1 个
数字产生 1 个逆序对 ([2,1]) ,因此后面 n - 1 个数必须要产生 
k - 1 个逆序对,故f(n, k) = f(n - 1, k - 1);

start = 3 时, [3, x, x, ..., x], 第一个数字 3 和后面的 n - 1 个
数字产生 2 个逆序对 ([3,1], [3, 2]) ,因此后面 n - 1 个数必须
要产生 k - 2 个逆序对,故f(n, k) = f(n - 1, k - 2);

start = 4 时, [4, x, x, ..., x], 第一个数字 4 和后面的 n - 1 个
数字产生 3 个逆序对 ([4,1], [4, 2], [4, 3]) ,因此后面 n - 1 个
数必须要产生 k - 3 个逆序对,故f(n, k) = f(n - 1, k - 3);

以此类推...

start = n 时, [n, x, x, ..., x], 第一个数字 n 和后面的 n - 1 个
数字产生 n - 1 个逆序对 ([n,1], [n, 2], ..., [n, n - 1]) ,因此后
面 n - 1 个数必须要产生 k - (n - 1) 个逆序对,
故f(n, k) = f(n - 1, k - (n - 1));


综上所述:f(n, k) = f(n - 1, k) + f(n - 1, k - 1) + ... 
                      + f(n - 1, k - (n - 1)); 其中 k >= (n - 1);

        f(n, k + 1) = f(n - 1, k + 1) + f(n - 1, k) + ... 
                      + f(n - 1, k + 1 - (n - 1)); 其中 (k + 1) >= (n - 1);

        f(n, k + 1) = f(n - 1, k + 1) + f(n, k) - f(n - 1, k - (n - 1))
                        = f(n, k) + f(n - 1, k + 1) - f(n - 1, k - (n - 1)); 其中 (k + 1) >= (n - 1);

当 k >= (n - 1) 时, f(n, k) = f(n, k - 1) + f(n - 1, k) - f(n - 1, k - 1 - (n - 1));
当 k <  (n - 1) 时, f(n, k) = f(n, k - 1) + f(n - 1, k);
class Solution {
public:
    int kInversePairs(int n, int k) {
        int MOD=1e9+7;
        int dp[1005][1005]={0};
        dp[1][0]=1;
        for (int i=2;i<1005;i++){
            dp[i][0]=1;
            for (int j=1;j<1005;j++){
               if (j>i-1){
                   dp[i][j]=(dp[i][j-1]+(dp[i-1][j]-dp[i-1][j-1-i+1]+MOD)%MOD)%MOD;
               }
               else {
                   dp[i][j]=(dp[i][j-1]+dp[i-1][j])%MOD;
               }
            }
        }
        return dp[n][k];
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值