Java实现通用组合算法

开发 后端 算法
Java是一种简单的,面向对象的,分布式的,解释型的,健壮安全的,结构中立的,可移植的,性能优异、多线程的动态语言。通用组合算法是经典数据结构算法。本文介绍的是通用组合算法用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));  
}  
}}} 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.

 

#p#

测试用例如下所示:

 

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(35this.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(35this.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(459270this.splitter.getFilteredContainer().size());  
}  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.

 

上述测试耗时大约2s左右。

上述算法实现主要是针对两种条件进行实现的,即:

***个是完全数字字符串 ——> 带有*号的组合数字字符串;

第二个带有*号的组合数字字符串 ——> 在该基础上继续组合得到带有*号的组合数字字符串。

如果使用上述算法实现处理***个条件,由于使用了列表List来记录索引,使执行速度略微低一点,比之于前面实现的不使用List列表来处理。

【编辑推荐】

  1. 何时创建Java对象实例
  2. 学习java编程的八大优势
  3. Java多线程程序设计详细解析
  4. 开发者最容易犯的13个JavaScript错误
责任编辑:于铁 来源: 帮考网
相关推荐

2011-04-20 11:22:51

Java

2017-02-13 17:17:48

Android标题栏控件

2021-01-30 11:10:51

算法回溯组合

2010-05-17 09:34:46

LINQAjax

2011-12-16 10:45:12

java

2021-06-22 09:44:56

鸿蒙HarmonyOS应用

2012-03-27 11:08:23

Java

2009-10-10 09:27:42

Java泛型通用方法

2009-12-23 09:04:41

LINQ通用分页

2014-04-23 16:54:51

神舟通用

2009-04-02 10:37:52

通用基类SQLLINQ

2017-02-09 16:16:24

Java负载均衡算法

2015-07-29 10:31:16

Java缓存算法

2022-09-09 15:01:37

物联网AIoT人工智能

2021-04-12 18:44:47

编程语言合子

2009-07-01 14:40:14

2012-03-07 10:34:44

Java

2012-06-27 15:33:30

Java排序算法

2021-03-04 17:55:27

算法Raft分布式

2023-11-18 09:48:23

点赞
收藏

51CTO技术栈公众号