LeetcodeのK Inverse Pairs Array
2713 ワード
タイトル:
Given two integers
We define an inverse pair as following: For
Since the answer may be very large, the answer should be modulo 109 + 7.
Example 1:
Example 2:
Note: The integer
コード:
方法1-タイムアウト、直接的な考え方:
方法2——時間最適化を行った後:
アイデア:いくつかの小さなtrickを使用します.
dp[n][k] = dp[n - 1][k] + dp[n - 1][k-1] + ... + dp[n - 1][k - n + 1]
kの代わりにk+1を使用して、次のようにすることができます.
dp[n][k+1] = dp[n - 1][k+1] + dp[n - 1][k] + ... + dp[n - 1][k + 1 - n + 1]
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の場合,最後の項の配列座標が非負の数になり,最後の項に値があることが分かったので,再更新する際にはkとnの関係を判断するだけで,k>=nの場合,最後の項を減算するという繰返し式がより効率的に計算され,サイクルが減少する
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:
n
is in the range [1, 1000] and k
is in the range [0, 1000]. コード:
方法1-タイムアウト、直接的な考え方:
class Solution {
public:
int kInversePairs(int n, int k) {
vector> v(n + 1, vector(k+1, 0));
v[1][0] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 0; j <= k; j++) {
int n = j;
while (n>=0&&n >= j-i+1) {
v[i][j]=(v[i][j]+v[i-1][n])%1000000007;
n--;
}
}
}
return v[n][k];
}
};
方法2——時間最適化を行った後:
class Solution {
public:
int kInversePairs(int n, int k) {
int M = 1000000007;
vector> dp(n + 1, vector(k + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= n; ++i) {
dp[i][0] = 1;
for (int j = 1; j <= k; ++j) {
dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % M;
if (j >= i) {
dp[i][j] = (dp[i][j] - dp[i - 1][j - i] + M) % M;
}
}
}
return dp[n][k];
}
};
アイデア:いくつかの小さなtrickを使用します.
dp[n][k] = dp[n - 1][k] + dp[n - 1][k-1] + ... + dp[n - 1][k - n + 1]
kの代わりにk+1を使用して、次のようにすることができます.
dp[n][k+1] = dp[n - 1][k+1] + dp[n - 1][k] + ... + dp[n - 1][k + 1 - n + 1]
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の場合,最後の項の配列座標が非負の数になり,最後の項に値があることが分かったので,再更新する際にはkとnの関係を判断するだけで,k>=nの場合,最後の項を減算するという繰返し式がより効率的に計算され,サイクルが減少する