我有一个多维数组,其大小是动态的。
String[][] array=new String[][]{{"1","2","3"},{"4","5","6"},{"7","8","9"},{"10","11","12"} };
我需要生成组合,例如每个组合长度必须位于1-array.length之间,并且每个组合可以包含一行中最多的一个元素。如果使用了一行中的列,则该组合中不能使用该行中的其他列。
例如,长度为1的组合是:
1
2
3
4
5
6
7
8
9
10
11
12
长度为2的组合是:
1,4
1,5
1,6
1,7
1,8
1,9
1,10
1,11
1,12
目前我只能得到长度= array.length的组合但我需要从1到array.length的长度
private String[][] generateCombinations(String[]... arrays) throws Throwable {
if (arrays.length == 0) {
return new String[][]{{}};
}
int num = 1;
for (int i = 0; i < arrays.length; i++) {
num *= arrays[i].length;
}
String[][] result = new String[num][arrays.length];
// array containing the indices of the Strings
int[] combination = new int[arrays.length];
for (int i = 0; i < num; i++) {
String[] comb = result[i];
// fill array
for (int j = 0; j < arrays.length; j++) {
comb[j] = arrays[j][combination[j]];
}
// generate next combination
for (int j = 0; j < arrays.length; j++) {
int n = ++combination[j];
if (n >= arrays[j].length) {
// "digit" exceeded valid range -> back to 0 and continue incrementing
combination[j] = 0;
} else {
// "digit" still in valid range -> stop
break;
}
}
}
return result;
}
答案 0 :(得分:1)
你喜欢1个字母的变量名吗? :D我甚至都不知道它现在是如何运作的。它使用位掩码来查找长度为n的子阵列的每个组合;然后它使用一些mod数学来从每个子阵列中找到1的每个组合;然后它吐出那个数字。排序顺序并不理想。
public class Perms {
private static String[][] array = new String[][] {
{ "1", "2", "3" },
{ "4", "5", "6" },
{ "7", "8", "9" },
{ "10", "11", "12" }
};
private static int combinationLength = 2;
public static void main(String[] args) {
// Get combinations of subarrays
for (int i = 0; i < Math.pow(2, array.length); ++i) {
int c = 0;
for (int j = 1; j <= Math.pow(2, array.length); j <<= 1)
if ((i & j) != 0)
++c;
if (c == combinationLength) {
String[][] maskedArray = new String[combinationLength][];
for (int l = 1, j = 0, k = 0; l <= Math.pow(2, array.length); l <<= 1, ++j)
if ((i & l) != 0) {
maskedArray[k] = array[j];
++k;
}
// Get combinations of one element per subarray
int l = 1;
for (int j = 0; j < maskedArray.length; ++j)
l *= maskedArray[j].length;
for (int j = 0; j < l; ++j) {
String s = "";
int m = j;
for (int k = maskedArray.length-1; k >= 0; --k) {
s = maskedArray[k][m % maskedArray[k].length] + "," + s;
m /= maskedArray[k].length;
}
// Spit out a result
System.out.println(s.substring(0, s.length()-1));
}
}
}
}
}
答案 1 :(得分:0)
好的,如果我得到了你的要求,请让我澄清一下。
您想要所有n个集合的组合,在任何组合中,您只能从一个集合中获取一个元素。 并且组合的长度可以是1到n的值。
所以基本上这是可行的算法。
基本上我们得到了 (2 ^ arraylength -1(未采取))*(P) P =每组中的元素数量这些组合。
所以基本上你要做的就是写一个递归函数给它像level,len。
这样的参数写一个for循环,使len从1变为n; 现在为i [1,len]的每个值 递归函数将按长度len的顺序打印所有组合。
所以你将获得长度1到arraylength()的所有组合 这是我写的代码,它不是可运行的,但它是我的算法的一个更容易理解的版本。
所以这就是你能做的。
int main()
{
string s=" ";
for(int i=0;i<=array.length;++i)
{
print-recur(array,s,arra.length,i,3,0);
}
return 0;
}
void print-recur(string array[][],string s[],int arlen,int len,int p,int level)
{
if(level>aralen)
return ;
else
{
if(len>0)
{
//this is not taking this level
if(len>aralen-level)
print-recur(a,s,arlen,len,p,level+1);
//the for loop is when the level is in the combination
for(i=0;i<p;++i)
{
s+=array[level][i];
print-recur(a,s,arlen,len-1,p,level+1);
str.erase( str.end()-1 );
}
}
else
cout<<s<<endl;
}
}
答案 2 :(得分:0)
如果有人正在寻找更灵活的解决方案,我会使用stream和reduce创建这个解决方案。你可以看到它在这里运行https://ideone.com/sSRrY3。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
class Combination {
private List<List<List<String>>> pairs = new ArrayList<>();
public Combination( List<String> elements ) {
this.pairs = createPairsFromElements( elements );
}
private Combination() {
}
public static Combination createFromPairs( String[][] arrPairs ) {
Combination combination = new Combination();
combination.pairs = createPairsFromArrayPairs(arrPairs);
return combination;
}
/**
* Create the pairs based on the String[][]
*
* Add the empty option at the beginner of each group
* Create the Lists and group them again
*
* @param arrPairs
* @return pairs
*/
private static List<List<List<String>>> createPairsFromArrayPairs( String[][] arrPairs ) {
List<List<List<String>>> pairs = new ArrayList<>();
for ( String[] groupValue: arrPairs ) {
List<List<String>> listGroupValue = new ArrayList<>();
/* add the empty value to the pairs */
listGroupValue.add(Arrays.asList());
for ( String value: groupValue ) {
List<String> listValue = Arrays.asList( value );
listGroupValue.add( listValue );
}
pairs.add( listGroupValue );
}
return pairs;
}
/**
* Convert the string list "a", "b", "c" to
* this:
* [
* [ [], [a] ], [ [], [b] ], [ [], [c] ]
* ]
*
* @param elements List of values to the collection
* @return pairs
*/
private static List<List<List<String>>> createPairsFromElements( List<String> elements ) {
return elements.stream().map(
(String value) -> {
List<List<String>> values = Arrays.asList(
Arrays.asList(), // immutable empty list
Arrays.asList( value ) // immutable atomic list
);
return values;
}
).collect(Collectors.toList());
}
/**
* Get the combination without restriction
*
* @param size
* @return
*/
public List<List<String>> getCombination( int size ) {
return this.getCombination( size, false );
}
/**
/*
* Combine every pair of elements creating a big list
* [ [], [b] ] x [ [], [a] ] = [ ([] + []), ([] + [a]), ([b] + []), ([b] + [a])) ] =
* [ [], [a], [b], [a, b] ]
* This keep working until add all elements.
*
* We filter to remove the combinations that are bigger than the max size
*
* @param size Max size of each result list
* @param restricted Should be exactly the received size.
* @return List of combinations
*/
public List<List<String>> getCombination( int size, boolean restricted ) {
List<List<String>> result = pairs.parallelStream().reduce(
new ArrayList<>(),
(acc,current) -> {
if( acc.size() == 0 ) {
return current;
}
List<List<String>> combinations = new ArrayList<>();
current.stream().forEach(
(List<String> valueCurrent ) -> acc.stream().forEach(
(List<String> valueAcc) -> {
List<String> combination = new ArrayList<>();
combination.addAll( valueAcc );
combination.addAll( valueCurrent );
if( combination.size() <= size ) {
combinations.add( combination );
}
}
)
);
return combinations;
}
);
if( ! restricted ) {
return result;
}
/* if the combination is size restricted, filter only elements with the exactly size */
return result.stream().filter( combination -> combination.size() == size ).
collect(Collectors.toList());
}
}
public class Main {
public static void main( String[] param ) {
Combination combination = new Combination(Arrays.asList("A","B","C","D","E"));
/* show all the combinations from 0 to 3 elements */
System.out.println( combination.getCombination(3));
// [
// [],
// [A],
// [B], [A, B],
// [C], [A, C], [B, C], [A, B, C],
// [D], [A, D], [B, D], [A, B, D], [C, D], [A, C, D], [B, C, D],
// [E], [A, E], [B, E], [A, B, E], [C, E], [A, C, E], [B, C, E], [D, E], [A, D, E], [B, D, E], [C, D, E]
// ]
/* show all the combinations with exactly 4 elements */
System.out.println( combination.getCombination(4, true));
// [
// [A, B, C, D],
// [A, B, C, E],
// [A, B, D, E],
// [A, C, D, E],
// [B, C, D, E]
// ]
Combination other = Combination.createFromPairs(
new String[][]{{"1","2","3"},{"4","5","6"},{"7","8","9"},{"10","11","12"} }
);
/* show all the combinations with exactly 3 elements */
System.out.println( other.getCombination(3, true));
// [
// [1, 4, 7], [2, 4, 7], [3, 4, 7], [1, 5, 7] ...
// ... [3, 9, 12], [4, 9, 12], [5, 9, 12], [6, 9, 12]
// ]
}
}