leetcode 629. K Inverse Pairs Array(K个降序对的数组)

Given two integers n and k, find how many different arrays consist of numbers from 1 to n such that there are exactly k inverse pairs.

We define an inverse pair as following: For ith and jth element in the array, if i < j and a[i] > a[j] then it’s an inverse pair; Otherwise, it’s not.

Since the answer may be very large, the answer should be modulo 109 + 7.

Example 1:

Input: n = 3, k = 0
Output: 1
Explanation:
Only the array [1,2,3] which consists of numbers from 1 to 3 has exactly 0 inverse pair.

Example 2:

Input: n = 3, k = 1
Output: 2
Explanation:
The array [1,3,2] and [2,1,3] have exactly 1 inverse pair.

Note:

The integer n is in the range [1, 1000] and k is in the range [0, 1000].

给出n和k,问有多少种排列方式可以使1~n的数中正好有k个降序对

思路:
0个数中有0个降序对的排列数是1
1~n的数如果是按升序排列,那么就是0个降序对,所以1~n的数中k=0的排列数也是1

剩下的,比如n=3, 数字是1,2,3,加入4的话可以有
[4,1,2,3], 在1,2,3的基础上增加3个降序对
[1,4,2,3], 在1,2,3的基础上增加2个降序对
[1,2,4,3], 在1,2,3的基础上增加1个降序对
[1,2,3,4], 在1,2,3的基础上增加0个降序对
所以在[1,2,3]的基础上增加4,可以增加0+1+2+3个降序对

定义dp[n][k],表示1~n的数字有k个降序对的排列数
所以dp[n][k] = dp[n-1][k] + dp[n-1][k-1] + dp[n-1][k-2] + … + dp[n-1][k-n+1] (1)

再简化一下
取k+1
dp[n][k+1] = dp[n-1][k+1] + dp[n-1][k] + dp[n-1][k-1] + … + dp[n-1][k-n+2] (2)
(2)式 - (1)式错位相消,得到
dp[n][k+1] - dp[n][k] = dp[n-1][k+1] - dp[n-1][k-n+1]
把k+1换成k,得到
dp[n][k] = dp[n][k-1] + dp[n-1][k] - dp[n-1][k-n]
其中最后一项只有在k >= n时才计算
注意,因为有减法,而且结果要取模,为了防止出现负数,减法时要+mod再取模

    public int kInversePairs(int n, int k) {
        int mod = 1000000007;
        int[][] dp = new int[n+1][k+1];
        dp[0][0] = 1;
        for(int i = 1; i <= n; i++) {
            dp[i][0] = 1;
            for(int m = 1; m <= k; m ++) {
                dp[i][m] = (dp[i][m-1] + dp[i-1][m]) % mod;
                if(m >= i) {
                    dp[i][m] = (dp[i][m] - dp[i-1][m-i] + mod) % mod;
                }
            }
            
        }
        return dp[n][k];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值