簡體   English   中英

長度為n的長度為3的不同子序列的數量

[英]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 = 3O(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM