您好,登錄后才能下訂單哦!
Java中怎么實現一個通用組合算法,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
Java實現通用組合算法,存在一個類似{31311133,33113330}這樣的集合,經過8取5組合,其他位置用非字母數字字符替代,比如使用*號,得到類似{3***1133,***13330,... ...}這樣的集合;
現在有這樣的需求:
存在一個類似{31311133,33113330}這樣的集合,經過8取5組合,其他位置用非字母數字字符替代,比如使用*號,得到類似{3***1133,***13330,... ...}這樣的集合;
還要求對于{3***1133,***13330}這樣的集合,再次經過5取3組合,其他位置用非字母數字字符替代,比如使用*號,得到類似{*****133,*****330,3***1*3*,... ...}這樣的集合。
對于這樣的要求,實現的思路如下:
首先,主要思想是基于信息編碼原理,通過掃描字符串,將10組合變為01組合。
其次,對于每個數字字符串,設置一個單線程,在單線程類中設置一個List用來存放待處理數字字符串(可能含有*號,或者不含有)中每個數字的(而非*號)索引位置值;
再次,設置BitSet來標志每個位置是否被*號替換得到新的組合字符串。
***,在掃描原始待處理數字字符串的過程中,根據設置的字符列表List中索引,來操作BitSet,對于每一個BitSet得到一個新的組合。
使用Java語言實現如下:
package org.shirdrn; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; /** * 通用組合拆分類(基于單線程) * 可以完成兩種功能: * ***,可以將完全數字串拆分成為含有*號的字符串。 * 例如:輸入集合{31311133,33113330},Splitter類會遍歷該集合,對每個字符串,創建一個SplitterThread * 線程來處理,如果是2取1組合,即starCount=8-2=6,經過線程處理得到類似******33,*****1*3等結果 * 第二,根據從帶有*號的字符串經過拆分過濾后得到的字符串集合,對其中每一個字符串進行組合 * 例如:輸入集合5取1組合字符串集合{3***1133,***113330} * CommonSplitter類會遍歷該集合,對每個帶有*號的字符串,創建一個SplitterThread * 線程來處理,如果是2串1組合,即starCount=8-3-2=3,經過線程處理得到類似******33,*****1*3等結果 * @author 時延軍 */ public class CommonSplitter { private int starCount; private boolean duplicate; private Collection filteredContainer; public Collection getFilteredContainer() { return filteredContainer; } /** * 構造一個Spilitter實例 * @param container 輸入的待處理字符串集合 * @param starCount 如果對于長度為N的數字字符串,進行M組合(即N取M),則starCount=N-M * @param duplicate 是否去重 */ public CommonSplitter(Collection container, int starCount, boolean duplicate) { this.duplicate = duplicate; this.starCount = starCount; if(this.duplicate) { // 根據指定是否去重的選擇,選擇創建容器 filteredContainer = Collections.synchronizedSet(new HashSet()); } else { filteredContainer = Collections.synchronizedList(new ArrayList()); } Iterator it = container.iterator(); while(it.hasNext()) { new Thread(new SplitterThread(it.next().trim())).start(); } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 對一個指定的N場比賽的長度為N的單式投注字符串進行組合 * 輸入單式投注注字符串string,例如31311133,組合得到類似******33,*****1*3,... ...結果的集合 * * @author 時延軍 */ class SplitterThread implements Runnable { private char[] charArray; private int len; // 數字字符的個數 List occupyIndexList = new ArrayList(); // 統計字符串中沒有帶*的位置的索引 private List container = new ArrayList(); private BitSet startBitSet; // 比特集合起始狀態 private BitSet endBitSet; // 比特集合終止狀態,用來控制循環 public SplitterThread(String string) { this.charArray = string.toCharArray(); this.len = string.replace("*", "").length(); this.startBitSet = new BitSet(len); this.endBitSet = new BitSet(len); // 初始化startBitSet,左側占滿*符號 int count = 0; // for (int i=0; i if(charArray[i] != '*') { if(count < starCount) { this.startBitSet.set(i, true); count++; } occupyIndexList.add(i); } } // 初始化endBit,右側占滿*符號 count =0; for (int i = string.length()-1; i > 0; i--) { if(charArray[i] != '*') { if(count < starCount) { this.endBitSet.set(i, true); count++; } ccupyIndexList.add(i); } } // 根據起始startBitSet,構造帶*的組合字符串并加入容器 char[] charArrayClone = this.charArray.clone(); for (int i=0; i if (this.startBitSet.get(i)) { charArrayClone[i] = '*'; } } this.container.add(new String(charArrayClone)); } public void run() { this.split(); synchronized(filteredContainer) { filteredContainer.addAll(this.container); }} public void split() { while(!this.startBitSet.equals(this.endBitSet)) { int zeroCount = 0; // 統計遇到10后,左邊0的個數 int oneCount = 0; // 統計遇到10后,左邊1的個數 int pos = 0; // 記錄當前遇到10的索引位置 char[] charArrayClone = this.charArray.clone(); // 遍歷startBitSet來確定10出現的位置 for (int i=0; i if (!this.startBitSet.get(this.occupyIndexList.get(i))) { zeroCount++; } if (this.startBitSet.get(this.occupyIndexList.get(i)) && !this.startBitSet.get(this.occupyIndexList.get(i+1))) { pos = i; oneCount = i - zeroCount; // 將10變為01 this.startBitSet.set(this.occupyIndexList.get(i), false); this.startBitSet.set(this.occupyIndexList.get(i+1), true); break; } } // 將遇到10后,左側的1全部移動到最左側 int count = Math.min(zeroCount, oneCount); int startIndex = this.occupyIndexList.get(0); int endIndex = 0; if(pos>1 && count>0) { pos--; endIndex = this.occupyIndexList.get(pos); for (int i=0; i this.startBitSet.set(startIndex, true); this.startBitSet.set(endIndex, false); startIndex = this.occupyIndexList.get(i+1); pos--; if(pos>0) { endIndex = this.occupyIndexList.get(pos); } }} // 將遇到1的位置用*替換 for (int i=0; i if (this.startBitSet.get(this.occupyIndexList.get(i))) { charArrayClone[this.occupyIndexList.get(i)] = '*'; } } this.container.add(new String(charArrayClone)); } }}}
測試用例如下所示:
package org.shirdrn; import java.util.ArrayList; import java.util.Collection; import junit.framework.TestCase; import org.shirdrn.util.GoodTools; public class TestCommonSplitter extends TestCase { private CommonSplitter splitter; public void setSplitter(Collection container, int starCount, boolean duplicate) { this.splitter = new CommonSplitter(container, starCount, duplicate); } public void testSplliter() { Collection container = new ArrayList(); container.add("1*10**"); int starCount = 2; boolean duplicate = true; this.setSplitter(container, starCount, duplicate); System.out.println(this.splitter.getFilteredContainer()); } public void testSplliter3() { Collection container = new ArrayList(); container.add("1*10*1300*"); int starCount = 3; boolean duplicate = true; this.setSplitter(container, starCount, duplicate); System.out.println(this.splitter.getFilteredContainer()); assertEquals(35, this.splitter.getFilteredContainer().size()); } public void testNoStar() { Collection container = new ArrayList(); container.add("3110330"); int starCount = 3; boolean duplicate = true; this.setSplitter(container, starCount, duplicate); System.out.println(this.splitter.getFilteredContainer()); assertEquals(35, this.splitter.getFilteredContainer().size()); } public void testSplitter_8_310() { // 8 場:310 String multiSeq = "310,310,310,310,310,310,310,310"; Collection container = GoodTools.getNSingleList(multiSeq); assertEquals(6561, container.size()); int starCount = 4; boolean duplicate = false; this.setSplitter(container, starCount, duplicate); assertEquals(459270, this.splitter.getFilteredContainer().size()); } }
上述測試耗時大約2s左右。
上述算法實現主要是針對兩種條件進行實現的,即:
***個是完全數字字符串 ——> 帶有*號的組合數字字符串;
第二個帶有*號的組合數字字符串 ——> 在該基礎上繼續組合得到帶有*號的組合數字字符串。
如果使用上述算法實現處理***個條件,由于使用了列表List來記錄索引,使執行速度略微低一點,比之于前面實現的不使用List列表來處理。
關于Java中怎么實現一個通用組合算法問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。