[英]No. of distinct subsequences of length 3 in an array of length n
如何計算長度的不同的子序列的數目3
(或一般長度的k < n
的長度的陣列) n
?
注意:如果兩個子序列中的元素順序不同,則認為它們是不同的。
例如:假設數組A = [1, 2, 1, 1]
1,2,1,1 A = [1, 2, 1, 1]
,那么答案應該是3
因為長度3
只有三個不同的子序列,如下所示:
[1, 1, 1]
[1, 2, 1]
[2, 1, 1]
數組的大小n <= 10^5
,數組A_i <= n
中的每個元素A_i <= n
。
我的方法:
我想到了蠻力方法,即采用長度為3
元組並將其插入地圖中。 但這不是空間/時間效率。
編輯 :這是一個采訪問題,它說, 對於k = 3 ,預期的時間和空間復雜度是O(n)
。
與面試問題一樣,有動態編程解決方案。 令T(m, k)
為前m
元素的不同長度k
序列的數量。 然后假設輸入A
有一個基於索引的索引,我們有2D重復
T(m, 0) = 1
T(m, k) = T(m-1, k) + T(m-1, k-1) -
^^^^^^^^^ ^^^^^^^^^^^
A_m not chosen A_m chosen
{ T(i-1, k-1), if i < m is the maximum index where A_i = A_m
{ 0, if no such index exists
減去的術語確保我們不計算重復項; 有關更多說明,請參閱https://stackoverflow.com/a/5152203/2144669 。
運行時間(使用哈希映射來保持到目前為止看到的每個符號的最右邊的出現)是O(kn)
,對於k = 3
是O(n)
。
這是一個略有不同的看法。 我們可以想到元素m
在子序列中可以是k
th的方式的數量,作為任何元素(包括m
)的先前出現的所有方式的總和可以是(k-1)
th。 然而,當我們向右移動時,唯一需要的更新是m
; 其他金額保持不變。
例如,
// We want to avoid counting [1,1,1], [1,2,1], etc. twice
[1, 2, 1, 1, 1]
(為方便起見,垂直顯示數組)
<- k ->
[1, -> 1: [1, 0, 0]
2, -> 2: [1, 1, 0]
1, -> 1: [1, 2, 1]
1, -> 1: [1, 2, 3]
1] -> 1: [1, 2, 3]
現在,如果我們添加另一個元素,比如說3,
...
3] -> 3: [1, 2, 3]
// 1 means there is one way
// the element, 3, can be first
// 2 means there are 2 ways
// 3 can be second: sum distinct
// column k[0] = 1 + 1 = 2
// 3 means there are 3 ways
// 3 can be third: sum distinct
// column k[1] = 2 + 1 = 3
求和k[2]
列:
0 + 3 + 3 = 6 subsequences
[1,2,1], [2,1,1], [1,1,1]
[1,1,3], [2,1,3], [3,2,1]
每列的sum-distinct可以在每次迭代中以O(1)
更新。 當前元素的k
和(我們更新每個元素的單個列表),取O(k)
,在我們的例子中是O(1)
。
JavaScript代碼:
function f(A, k){ A.unshift(null); let sumDistinct = new Array(k + 1).fill(0); let hash = {}; sumDistinct[0] = 1; for (let i=1; i<A.length; i++){ let newElement; if (!hash[A[i]]){ hash[A[i]] = new Array(k + 1).fill(0); newElement = true; } let prev = hash[A[i]].slice(); // The number of ways an element, m, can be k'th // in the subsequence is the sum of all the ways // the previous occurence of any element // (including m) can be (k-1)'th for (let j=1; j<=k && j<=i; j++) hash[A[i]][j] = sumDistinct[j - 1]; for (let j=2; j<=k && j<=i; j++) sumDistinct[j] = sumDistinct[j] - prev[j] + hash[A[i]][j]; if (newElement) sumDistinct[1] += 1; console.log(JSON.stringify([A[i], hash[A[i]], sumDistinct])) } return sumDistinct[k]; } var arr = [1, 2, 1, 1, 1, 3, 2, 1]; console.log(f(arr, 3));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.