java 有序列表_关于算法:在Java中为列表列表生成唯一的有序非重复组合
我知道有很多類(lèi)似的問(wèn)題,并且已經(jīng)閱讀了幾個(gè)小時(shí)。但是它們似乎都不符合我的要求。
我有列表列表(list >),列表可以是任何大小。
例:
我的外部列表大小是:4
清單內(nèi)容
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)
...
...等等
我必須通過(guò)從每個(gè)列表中選擇一個(gè)元素來(lái)生成組合
組合長(zhǎng)度最大為4(外部列表的大小),如果組合中得到相同的元素,有時(shí)會(huì)縮小
我的組合數(shù)量將是每個(gè)內(nèi)部列表中元素?cái)?shù)量的乘積。
在上面的示例中,組合數(shù)量為3x4x2x5=120組合
由于我的列表包含重復(fù)元素,因此我也會(huì)得到重復(fù)組合
在這里,如果我有adab adba,則adba是重復(fù)項(xiàng),因?yàn)轫樞驘o(wú)關(guān)緊要。
問(wèn)題是我使用簡(jiǎn)單的方法生成組合,如果我的外部列表大小增加并且內(nèi)部列表包含更多元素,我最終將生成數(shù)百萬(wàn)個(gè)組合,但是只有1000或2000個(gè)是唯一的,其余都是重復(fù)項(xiàng)。
是否有任何算法方法僅生成唯一組合而不是生成所有組合?
all-domain-sets-union的累積集積可以創(chuàng)建所有可能的組合,并且沒(méi)有重復(fù)項(xiàng)
1:這是作業(yè)嗎?
2:您預(yù)計(jì)最多使用幾個(gè)列表?
基本上...將不會(huì)有某種神奇的方法來(lái)執(zhí)行此操作...您將不得不檢查所構(gòu)建的字符串是否已經(jīng)包含要考慮添加的字母,這就是您要優(yōu)化-檢查您的字符串是否已經(jīng)包含字母。
如果您正在做家庭作業(yè),我認(rèn)為您可以使用String.contains('a')|| String.contains('A')以查看String是否已經(jīng)包含某個(gè)字母(在這種情況下為'a')。剩下的我留給你。請(qǐng)注意,這是O(n ^ 2)運(yùn)算。
如果您是為了更工業(yè)應(yīng)用而這樣做,那么我會(huì)看到另一個(gè)選擇。
如果要使用大量的字符串列表,則可能需要使用TreeSet來(lái)存儲(chǔ)已經(jīng)使用過(guò)的字符列表。例如,瀏覽完第一個(gè)列表(a,b,c)后,您將看到"二手字符"的樹(shù)集是否包含" a",否則,您將在字符串中添加" a"并在使用的字符的TreeSet中添加" a"。然后,您將轉(zhuǎn)到第二個(gè)列表,查看您的TreeSet是否包含字母d,依此類(lèi)推。總的來(lái)說(shuō),這將是一個(gè)o(n * log(n))函數(shù)。
使用TreeSet來(lái)存儲(chǔ)"已用"字符列表的好處是,使用o來(lái)添加和檢查字符要花費(fèi)o(log(n)),而使用o來(lái)檢查String中的字符要花費(fèi)o(n)。 contains(" a")。 (您甚至可以在添加/檢查之前將所有內(nèi)容都轉(zhuǎn)換為小寫(xiě)。)
使用TreeSet的缺點(diǎn)是,僅實(shí)例化TreeSet會(huì)產(chǎn)生適度的開(kāi)銷(xiāo),如果僅使用小的字符串列表,則可能不值得。
問(wèn)題:為什么要有一個(gè)字符串列表而不是一個(gè)字符列表?似乎字符列表更合適。
如果您不熟悉o(n ^ 2),o(log(n))或o(n)的含義,那么o(whatever)只是一種近似表示函數(shù)運(yùn)行時(shí)間如何擴(kuò)展的表示法以及傳遞給該函數(shù)的參數(shù)數(shù)量。
-例如,如果您運(yùn)行帶有4個(gè)參數(shù)的o(n ^ 2)函數(shù),則將花費(fèi)4 ^ 2 == 16時(shí)間(其中"時(shí)間"是任意時(shí)間單位)。如果使用8個(gè)參數(shù)運(yùn)行它,則將花費(fèi)8 ^ 2 == 64時(shí)間。隨著輸入大小的增加,它會(huì)平方增加。
-例如,如果您運(yùn)行帶有4個(gè)參數(shù)的o(n)函數(shù),它將執(zhí)行4次。如果您運(yùn)行帶有8個(gè)參數(shù)的o(n)函數(shù),則將花費(fèi)8次。
-例如,如果您運(yùn)行帶有4個(gè)參數(shù)的o(log(n))函數(shù),則將花費(fèi)2倍的時(shí)間。如果您運(yùn)行帶有8個(gè)參數(shù)的o(log(n))函數(shù),則將花費(fèi)3倍的時(shí)間。 (假設(shè)日志以2為底。)
希望您能想到-關(guān)鍵是o(n ^ 2),o(n * log(n)),o(n)和o(log(n))之間的差很小,且數(shù)字很小,但是一旦您開(kāi)始獲得大小為100或更大的列表,這將非常重要-o(n ^ 2)將花費(fèi)10,000時(shí)間,而o(n * log(n))將花費(fèi)大約670時(shí)間-就是說(shuō),只有100個(gè)列表,它將快15倍。在1000個(gè)列表上,它將快100倍。
謝謝回復(fù)。實(shí)際上,它是具有更多內(nèi)容的對(duì)象列表(域類(lèi)代表一個(gè)表),它是一項(xiàng)業(yè)務(wù)需求并且是機(jī)密的,因此我使用字母并將其引用為L(zhǎng)ist >而不是List >。我預(yù)計(jì)最多可以有20個(gè)內(nèi)部列表,但是每個(gè)內(nèi)部列表的大小最大為30。..問(wèn)題是,當(dāng)我得到更大的列表時(shí),處理List >需要2到5分鐘,我可能最多20000列表>。因此需要100多個(gè)小時(shí)才能完成。需要邏輯在3到4個(gè)小時(shí)內(nèi)處理
嗯。今天上班時(shí)我有個(gè)主意。如果您有20個(gè)內(nèi)部列表,我想我知道一種使用遞歸算法使其運(yùn)行速度快19倍的方法(與僅對(duì)20個(gè)內(nèi)部列表進(jìn)行天真的迭代相比)。此外,使用TreeSet可能會(huì)使它運(yùn)行快2倍。最后,我在Intel i7 930上使用多線程處理器的經(jīng)驗(yàn)表明,盡管您將使用幾乎所有的CPU容量,但您可以使處理器運(yùn)行速度提高5倍(ish)。所以...希望我們可以減少您的時(shí)間。等待第二篇關(guān)于遞歸思想的文章。
你知道什么...我應(yīng)該更了解。這個(gè)問(wèn)題是NP難題。在大小為5的10個(gè)內(nèi)部列表上運(yùn)行大約需要5.6秒,但將其跳至11則需要28秒。 12個(gè)內(nèi)部列表需要137秒。 (由于每個(gè)內(nèi)部列表都有5個(gè)字符,因此添加的每個(gè)內(nèi)部列表都會(huì)增加5倍。)
我徹底被淘汰了。問(wèn)題是NP難的。建議您找到一種不同的方式來(lái)做您想做的事。
編輯:只需重新閱讀您的原始帖子即可。昨晚我看完之后好像您已對(duì)其進(jìn)行了編輯……我現(xiàn)在看到您不是在要求以下算法,而是在要求其他東西。 = /會(huì)考慮的,但可能什么也不會(huì)想出來(lái)。
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;
}
感謝您為我提供更好解決方案的努力。
總結(jié)
以上是生活随笔為你收集整理的java 有序列表_关于算法:在Java中为列表列表生成唯一的有序非重复组合的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java 接口中 常量_讨论:Java
- 下一篇: java跳槽原因_跳槽求职必看:Java