java 有序列表_关于算法:在Java中为列表列表生成唯一的有序非重复组合
我知道有很多類似的問題,并且已經閱讀了幾個小時。但是它們似乎都不符合我的要求。
我有列表列表(list >),列表可以是任何大小。
例:
我的外部列表大小是:4
清單內容
1. list(0) a,b,c ? ? ? ? ? ? ? ?size:3
2. list(1) d,b,f,m ? ? ? ? ? ? size:4
3. list(2) x,a ? ? ? ? ? ? ? ? ? ? size:2
4. list(3) b,e,d,m,a ? ? ? ? ?size:5
這是我的組合
adxb
adxe
adxd (adx) duplicate element will be removed after generating combination
adxm
adxa (adx)
adab (adb)
adae (ade)
...
...等等
我必須通過從每個列表中選擇一個元素來生成組合
組合長度最大為4(外部列表的大小),如果組合中得到相同的元素,有時會縮小
我的組合數量將是每個內部列表中元素數量的乘積。
在上面的示例中,組合數量為3x4x2x5=120組合
由于我的列表包含重復元素,因此我也會得到重復組合
在這里,如果我有adab adba,則adba是重復項,因為順序無關緊要。
問題是我使用簡單的方法生成組合,如果我的外部列表大小增加并且內部列表包含更多元素,我最終將生成數百萬個組合,但是只有1000或2000個是唯一的,其余都是重復項。
是否有任何算法方法僅生成唯一組合而不是生成所有組合?
all-domain-sets-union的累積集積可以創建所有可能的組合,并且沒有重復項
1:這是作業嗎?
2:您預計最多使用幾個列表?
基本上...將不會有某種神奇的方法來執行此操作...您將不得不檢查所構建的字符串是否已經包含要考慮添加的字母,這就是您要優化-檢查您的字符串是否已經包含字母。
如果您正在做家庭作業,我認為您可以使用String.contains('a')|| String.contains('A')以查看String是否已經包含某個字母(在這種情況下為'a')。剩下的我留給你。請注意,這是O(n ^ 2)運算。
如果您是為了更工業應用而這樣做,那么我會看到另一個選擇。
如果要使用大量的字符串列表,則可能需要使用TreeSet來存儲已經使用過的字符列表。例如,瀏覽完第一個列表(a,b,c)后,您將看到"二手字符"的樹集是否包含" a",否則,您將在字符串中添加" a"并在使用的字符的TreeSet中添加" a"。然后,您將轉到第二個列表,查看您的TreeSet是否包含字母d,依此類推。總的來說,這將是一個o(n * log(n))函數。
使用TreeSet來存儲"已用"字符列表的好處是,使用o來添加和檢查字符要花費o(log(n)),而使用o來檢查String中的字符要花費o(n)。 contains(" a")。 (您甚至可以在添加/檢查之前將所有內容都轉換為小寫。)
使用TreeSet的缺點是,僅實例化TreeSet會產生適度的開銷,如果僅使用小的字符串列表,則可能不值得。
問題:為什么要有一個字符串列表而不是一個字符列表?似乎字符列表更合適。
如果您不熟悉o(n ^ 2),o(log(n))或o(n)的含義,那么o(whatever)只是一種近似表示函數運行時間如何擴展的表示法以及傳遞給該函數的參數數量。
-例如,如果您運行帶有4個參數的o(n ^ 2)函數,則將花費4 ^ 2 == 16時間(其中"時間"是任意時間單位)。如果使用8個參數運行它,則將花費8 ^ 2 == 64時間。隨著輸入大小的增加,它會平方增加。
-例如,如果您運行帶有4個參數的o(n)函數,它將執行4次。如果您運行帶有8個參數的o(n)函數,則將花費8次。
-例如,如果您運行帶有4個參數的o(log(n))函數,則將花費2倍的時間。如果您運行帶有8個參數的o(log(n))函數,則將花費3倍的時間。 (假設日志以2為底。)
希望您能想到-關鍵是o(n ^ 2),o(n * log(n)),o(n)和o(log(n))之間的差很小,且數字很小,但是一旦您開始獲得大小為100或更大的列表,這將非常重要-o(n ^ 2)將花費10,000時間,而o(n * log(n))將花費大約670時間-就是說,只有100個列表,它將快15倍。在1000個列表上,它將快100倍。
謝謝回復。實際上,它是具有更多內容的對象列表(域類代表一個表),它是一項業務需求并且是機密的,因此我使用字母并將其引用為List >而不是List >。我預計最多可以有20個內部列表,但是每個內部列表的大小最大為30。..問題是,當我得到更大的列表時,處理List >需要2到5分鐘,我可能最多20000列表>。因此需要100多個小時才能完成。需要邏輯在3到4個小時內處理
嗯。今天上班時我有個主意。如果您有20個內部列表,我想我知道一種使用遞歸算法使其運行速度快19倍的方法(與僅對20個內部列表進行天真的迭代相比)。此外,使用TreeSet可能會使它運行快2倍。最后,我在Intel i7 930上使用多線程處理器的經驗表明,盡管您將使用幾乎所有的CPU容量,但您可以使處理器運行速度提高5倍(ish)。所以...希望我們可以減少您的時間。等待第二篇關于遞歸思想的文章。
你知道什么...我應該更了解。這個問題是NP難題。在大小為5的10個內部列表上運行大約需要5.6秒,但將其跳至11則需要28秒。 12個內部列表需要137秒。 (由于每個內部列表都有5個字符,因此添加的每個內部列表都會增加5倍。)
我徹底被淘汰了。問題是NP難的。建議您找到一種不同的方式來做您想做的事。
編輯:只需重新閱讀您的原始帖子即可。昨晚我看完之后好像您已對其進行了編輯……我現在看到您不是在要求以下算法,而是在要求其他東西。 = /會考慮的,但可能什么也不會想出來。
public static void main(String[] args) {
long runningTime = 0;
int numTrials = 1;
for( int i = 0; i < numTrials; i++ )
{
List> theLists = UniqueStringTest.makeListOfLists(12, 5);
long startTime = System.currentTimeMillis();
RecursiveAnalyzer ra = new RecursiveAnalyzer( theLists );
ra.run();
runningTime += ( System.currentTimeMillis() - startTime );
}
System.out.println("Finished" + numTrials +" trials in" +
runningTime +" milliseconds." );
}
public static class RecursiveAnalyzer implements Runnable
{
private List> theLists;
private Stack buildingString;
private TreeSet usedChars;
public RecursiveAnalyzer( List> newTheLists )
{
this.theLists = newTheLists;
}
public void run()
{
this.usedChars = new TreeSet<>();
this.buildingString = new Stack<>();
recursiveAnalysisHelper( 0 );
}
protected void recursiveAnalysisHelper( int currentDepth )
{
List currentList = this.theLists.get( currentDepth );
boolean haveOneOnStack = false;
//Iterate over each character in list number currentDepth
for( int i = 0; i < currentList.size(); i++ )
{
if ( this.usedChars.contains( currentList.get(i) ) == false )
{
this.usedChars.add( currentList.get(i) );
this.buildingString.push( currentList.get(i) );
haveOneOnStack = true;
}
else
{
haveOneOnStack = false;
}
if ( (currentDepth+1) < this.theLists.size() )
{
recursiveAnalysisHelper( currentDepth+1 );
}
else
{
String answer ="";
for( String s : this.buildingString )
{
answer += s;
}
//System.out.println(answer);
}
if( haveOneOnStack == true )
{
this.buildingString.pop();
this.usedChars.remove( currentList.get(i) );
}
}
}
}
public static List> makeListOfLists( int numLists, int numChars )
{
List> answer = new ArrayList<>();
Random rand = new Random();
if ( numChars > 25 )
{
numChars = 25;
}
for( int i = 0; i < numLists; i++ )
{
List anInnerList = new ArrayList<>();
for( int j = 0; j < numChars; )
{
//Makes a lowercase letter
String aChar = Character.toString((char)(rand.nextInt(26)+97));
if ( anInnerList.contains( aChar ) == false )
{
anInnerList.add( aChar );
j++;
}
}
answer.add(anInnerList);
}
return answer;
}
感謝您為我提供更好解決方案的努力。
總結
以上是生活随笔為你收集整理的java 有序列表_关于算法:在Java中为列表列表生成唯一的有序非重复组合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 接口中 常量_讨论:Java
- 下一篇: java跳槽原因_跳槽求职必看:Java