2015-07-05 71 views
-6

我有一個矩陣6000x20,包含的數字範圍是1-80。我需要查找出現在矩陣中的所有六元組。我需要最高效和最快的解決方案。 我目前的解決辦法是這樣做的: 1.我從矩陣中取第一行併產生所有的六行字(38600在一行中) 2.我把每一個六行字與其他5999行進行比較並計算它們 3.我把它們寫入一個文件,因爲我的存儲空間已滿相當快 4.我把第二排和生成所有sextuplets我又查找大數組中最常見的六個字母組合

這種算法是非常糟糕和IM意識到這一點,因爲我有38600X6000比較和可能的文件寫入完成所有步驟,我有很多重複的六重音。但我不知道,因爲我不能使用這種大小的變量。

我需要的算法解決方案,因此我可以在Matlab/JAVA/C++ /蟒

+0

決定一種語言來得到一個簡潔和正確的答案。 –

+0

讓它成爲C++,我猜它是最快的 – Djuro

+0

它的對,三連音... sextuplets。我需要找出六個數字的組合是最常見的 – Djuro

回答

1

由於值的範圍爲1-80,可能sextuplets的總數是「唯一」的一個稍微超過3億寫(準確地說300,500,200)。由於矩陣中只有6000行,因此任何六進制數的最大計數都是6000,所以計數可以很容易地適合兩個字節的整數(假設存在於C++實現中,則爲uint16_t)。三億兩個字節的整數總共600兆字節,你可能已經有了。所以一個簡單的算法就是創建計數向量,初始化爲零,然後迭代矩陣中的所有行;對於每一行,遍歷38,760個六元組,並對每個六元組遞增相應的計數。

訣竅是計算出計數向量中的哪個元素對應給定的六個數字集合。碰巧,只要六個字符的數字從最小到最大,這並不難。 (這不是一個限制,因爲你需要有一些規範的順序爲六元組,並按順序排序是一個簡單的規範順序。)

要了解如何生成索引,請考慮如何(假設)枚舉所有300,500,200來自集合{1..80}的六個整數的組合。首先,我們列舉以1開始的組合,並繼續使用集合{2..80}中的五個整數。然後,我們枚舉以2開始的組合,並繼續使用集合{3..80}中的五個整數。然後,我們枚舉以3開始的組合,並繼續使用集合{4..80}中的5個整數。等等。在每個起點的枚舉中,我們遞歸地應用相同的算法。

現在,讓我們把它列在頭上。假設我們有一些六聯{a,b,c,d,e,f}。請問之後有多少個六進制碼出現那sextuplet?

  • 首先,所有以大於a的值開始的六個字符串。由於六個字符串是有序的,如果一個六元組的起始值大於a,那麼它的所有值都大於a,這意味着它是來自集合{a+1..80}的六個值的某種組合,其中有 80-a C 。

  • 然後,所有六個字符串都以a開頭,並繼續五元組,第一個值大於b。通過上述相同的邏輯,這樣的六個小組的數目是 80-b C 。

  • 然後,存在與開始a,b並繼續四方其第一值大於c更大所有sextuplets:共 80-C的C

  • 等等

所以以下{a,b,c,d,e,f} sextuplets總數恰恰是:

80-AÇ + 80-BÇ + 80-CÇ + 80-dÇ + 80-EÇ + 80-Fç

有趣關於上面的等式是,有六個變量之間沒有相互作用。我們可以通過創建六個查找表來計算值,其值爲1到80之間的值,以及i的值從1到6.然後我們可以計算(逆)指數通過只進行六次查找並將值加在一起來確定任何六進制數。 (如果需要的話,我們可以從組合總數中減去反向索引以得到正向索引,但是在這種情況下,我們需要的是從組合到整數的雙向反射,反向索引將正常工作。)

在算法結束時,有必要將計數索引變回六個字節。這可以使用相同的查找表,通過執行二進制搜索的連續操作來完成:首先,在i == 6的查找表中通過二進制搜索找到值a,然後減去相應的索引並繼續搜索餘數i == 5的查找表等等(實際上,由於查找表很小,可能會發現線性搜索比二元搜索更快,但它可能沒有多大區別。)

+0

謝謝,這是一個很好的答案,它幫助了我很多 – Djuro