有时候会有需求 从N个数组个各取1个元素组成新数组,问有多少种可能,分别是什么?(这里假设不涉及重复元素和顺序影响)
类似 [a,b,c,d],[1,2],[A,B,F] 3个数组个各取一个元素组成新数组,共计24种可能,结果分别如下:
[a,1,A],[a,1,B],[a,1,F],[a,2,A],[a,2,B],[a,2,F],[b,1,A],[b,1,B]......[d,2,A],[d,2,B],[d,2,F].
那如何用程序来完成这个数学问题呢?下面先介绍思路,再用java代码尝试code。
每次从3个数组中各取一个元素,取元素的下标初始默认分别是0->(0,0,0),即:第一个数组是"a",第二个数组是"1",第三个数组是"A"; 下一个新数组来源的下标呢?前2个还是0,第三个加1->(0,0,1),同理,再下一个呢?(0,0,2),再下一个呢? 是0,0,3吗?
这里需要注意一下,当取元素的数组的下标越界(>=当前数组的长度)时,我们需要将当前元素的数组的下标置为0,前一个数组的下标加1,所以(0,0,2)后面一个下标应该是(0,1,0);后面规律就一样了。
看这个过程像什么呢?是不是类似进制数+1的过程?
如果是10进制的,2个数组就类似组成两位数,3个数组类似组成3位数。可能性= 10*10*...*10,有多少个数组就有10N种可能
如果是2进制的,即,每个源数组都有2个元素,那可能性=2*2*...*2 有多少个数组就有2N种可能;
现在数组长度是不规律的,可能性= 每个数组元素个数乘积,上方示例可能=4*2*3=24种;
知道了过程和原理开始撸代码吧:
给出的参数就是1个集合,集合的每个元素是1个数组
List<String[]> originalList
首先需要2个临时变量数组,分别存放原数组取数的下标和原数组的长度
int[] tempIndexArr = new int[originalList.size()];
int[] tempLengthArr = new int[originalList.size()];
需要1个集合存放新组成的数组
List<String[]> combineList = new ArrayList<>();
需要一个是否完成遍历的flag
boolean completeFlag = false;
最核心的逻辑,其实也很简单,就是取下标索引:
int changeIndex = originalList.size() - 1;
boolean isRightIndex = false;
while (!isRightIndex) {
tempIndexArr[changeIndex] += 1;
if(tempIndexArr[changeIndex] >= tempLengthArr[changeIndex]) {
tempIndexArr[changeIndex--] = 0;
} else {
isRightIndex = true;
}
}
取到了下标索引,从原集合中根据下标索引取数组成新数组放到新集合中
String[] newItem = new String[originalList.size()];
for (int i = 0; i < originalList.size() ; i++) {
newItem[i] = originalList.get(i)[tempIndexArr[i]];
}
combineList.add(newItem);
基本过程就结束了。 不过这里需要增加一个判断 就是是否遍历完了,判断逻辑是 下标都已经到了最大值,完成代码、测试和打印结果如下
package work;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
/**
* @author lixiaoming
* @date 2019/6/19 16:53
*/
public class CombineTest {
public static void main(String[] args) {
List<String[]> originalList = new ArrayList<>();
originalList.add(new String[] {"a", "b", "c", "d"});
originalList.add(new String[] {"1", "2"});
originalList.add(new String[] {"A", "B", "F"});
List<String[]> combineList = getCombineList(originalList);
System.out.println("组成的新集合共有" + combineList.size() + "个数组");
combineList.forEach(s-> {
System.out.println(StringUtils.join(s, ","));
});
}
private static List<String[]> getCombineList(List<String[]> originalList) {
int originalSize = originalList.size();
int[] tempIndexArr = new int[originalSize];
tempIndexArr[originalSize - 1] = -1;
int[] tempLengthArr = new int[originalSize];
for (int i = 0; i < originalSize ; i++) {
tempLengthArr[i] = originalList.get(i).length;
}
List<String[]> combineList = new ArrayList<>();
boolean completeFlag = false;
while(!completeFlag) {
int changeIndex = originalList.size() - 1;
boolean isRightIndex = false;
while (!isRightIndex) {
tempIndexArr[changeIndex] += 1;
if(tempIndexArr[changeIndex] >= tempLengthArr[changeIndex]) {
if(changeIndex == 0) {
isRightIndex = true;
completeFlag = true;
} else {
tempIndexArr[changeIndex--] = 0;
}
} else {
isRightIndex = true;
}
}
if(isRightIndex && !completeFlag) {
String[] newItem = new String[originalList.size()];
for (int i = 0; i < originalList.size() ; i++) {
newItem[i] = originalList.get(i)[tempIndexArr[i]];
}
combineList.add(newItem);
}
}
return combineList;
}
}
打印结果如下:
组成的新集合共有24个数组
a,1,A
a,1,B
a,1,F
a,2,A
a,2,B
a,2,F
b,1,A
b,1,B
b,1,F
b,2,A
b,2,B
b,2,F
c,1,A
c,1,B
c,1,F
c,2,A
c,2,B
c,2,F
d,1,A
d,1,B
d,1,F
d,2,A
d,2,B
d,2,F
Process finished with exit code 0

958

被折叠的 条评论
为什么被折叠?



