給出兩個整數 n 和 k,找出所有包含從 1 到 n 的數字,且恰好擁有 k 個逆序對的不同的陣列的個數。
逆序對的定義如下:對於陣列的第i個和第 j個元素,如果滿i < j且 a[i] > a[j],則其為乙個逆序對;否則不是。
由於答案可能很大,只需要返回 答案 mod 109 + 7 的值。
示例 1:
輸入: n = 3, k = 0
輸出: 1
解釋:
只有陣列 [1,2,3] 包含了從1到3的整數並且正好擁有 0 個逆序對。
示例 2:
輸入: n = 3, k = 1
輸出: 2
解釋:
陣列 [1,3,2] 和 [2,1,3] 都有 1 個逆序對。
說明:
n 的範圍是 [1, 1000] 並且 k 的範圍是 [0, 1000]。
動態規劃
dp[i][j]表示前i的數字,恰好擁有j個逆序對,也就是1~i擁有j個逆序對
初始條件dp[0][0] = 1
轉移方程dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + dp[i-1][j-2] + ······+dp[i-1][j-i+1]
也就是我們考慮dp[i][j] 時需要考慮i這個數字的存放位置,我們可以放在最後乙個位置,那麼逆序對會增加0個,也就是我們需要考慮dp[i-1][j];我們可以放在倒數第二個位置,那麼逆序對會增加1個,我們就需要考慮dp[i-1][j-1],依次類推。
但是,這樣的時間複雜度為o(n2k),我們可以對其進行優化。
我們不妨令j=j-1,那麼dp[i][j-1] = dp[i-1][j-1] + dp[i-1][j-2] + dp[i-1][j-3] + ······+dp[i-1][j-i]
我們讓dp[i][j]-dp[i][j-1],得到dp[i][j] = dp[i-1][j] - dp[i-1][j-i] + dp[i][j-1],因此可以把時間複雜度變為o(nk)。詳細過程見**
int
kinversepairs
(int n,
int k)}}
return dp[n]
[k];
}
Leetcode 629 K個逆序對陣列
給出兩個整數 n 和 k,找出所有包含從 1 到 n 的數字,且恰好擁有 k 個逆序對的不同的陣列的個數。逆序對的定義如下 對於陣列的第i個和第 j個元素,如果滿i j且 a i a j 則其為乙個逆序對 否則不是。由於答案可能很大,只需要返回 答案 mod 109 7 的值。示例 1 輸入 n 3...
LeetCode 629 K個逆序對陣列
略。首先,1 n 這 n 個數所能產生的最大逆序對為 n n 1 2 對。設 dp i j 表示 1 i 能產生 j 對逆序對的排列種數。這裡定義一下如果下標為負數,這一項為 0。在考慮接下來乙個事實 對於序列 1,2,3,4,5 和 2,5,7,9,10,在這個問題下,我可以說這兩個序列是等價的,...
629 K個逆序對陣列
給出兩個整數 n 和 k,找出所有包含從 1 到 n 的數字,且恰好擁有 k 個逆序對的不同的陣列的個數。逆序對的定義如下 對於陣列的第i個和第 j個元素,如果滿i j且 a i a j 則其為乙個逆序對 否則不是。由於答案可能很大,只需要返回 答案 mod 109 7 的值。示例 1 輸入 n 3...