629. K Inverse Pairs Array

87 篇文章 0 订阅

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 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:

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

 

思路:直觉是DP,第3层循环枚举最大值得位置

public class Solution {
    public int kInversePairs(int n, int k) {
        long[][] dp = new long[n+1][k+1];
        
        for(int i=0; i<=n; i++)
        	dp[i][0] = 1;
        
        for(int i=1; i<=n; i++)
        	for(int j=1; j<=k; j++) {
        		for(int q=0; q<=j; q++) {
        			if(i-1 >= j-q) {
        				dp[i][j] += dp[i-1][q];
        				dp[i][j] %= 1000000007;
        			}
        		}
        	}
        
        return (int) dp[n][k];
    }
}


TLE,原来dp过程有枚举过程,而且重复dp[i][j-1]的枚举过程,可以进行状态压缩

package l629;
/*
 * 自觉告诉我DP
 * 状态压缩,dp过程有枚举过程,而且重复dp[i][j-1]的枚举过程
 */
public class Solution {
    public int kInversePairs(int n, int k) {
        long[][] dp = new long[n+1][k+1];
        
        for(int i=0; i<=n; i++)
        	dp[i][0] = 1;
        
        for(int i=1; i<=n; i++)
        	for(int j=1; j<=k; j++) {
        		dp[i][j] = dp[i][j-1]+dp[i-1][j];
        		if(j-i >= 0) dp[i][j] -= dp[i-1][j-i];
        		dp[i][j] += 1000000007;
        		dp[i][j] %= 1000000007;
        	}
        
        return (int) dp[n][k];
    }
}

 

 

 

 

dp[n][k] denotes the number of arrays that have k inverse pairs for array composed of 1 to n
we can establish the recursive relationship between dp[n][k] and dp[n-1][i]:

 

if we put n as the last number then all the k inverse pair should come from the first n-1 numbers
if we put n as the second last number then there's 1 inverse pair involves n so the rest k-1 comes from the first n-1 numbers
...
if we put n as the first number then there's n-1 inverse pairs involve n so the rest k-(n-1) comes from the first n-1 numbers

 

dp[n][k] = dp[n-1][k]+dp[n-1][k-1]+dp[n-1][k-2]+...+dp[n-1][k+1-n+1]+dp[n-1][k-n+1]

 

It's possible that some where in the right hand side the second array index become negative, since we cannot generate negative inverse pairs we just treat them as 0, but still leave the item there as a place holder.

 

dp[n][k] = dp[n-1][k]+dp[n-1][k-1]+dp[n-1][k-2]+...+dp[n-1][k+1-n+1]+dp[n-1][k-n+1]
dp[n][k+1] = dp[n-1][k+1]+dp[n-1][k]+dp[n-1][k-1]+dp[n-1][k-2]+...+dp[n-1][k+1-n+1]

 

so by deducting the first line from the second line, we have

 

dp[n][k+1] = dp[n][k]+dp[n-1][k+1]-dp[n-1][k+1-n]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值