我正在尝试创建一个程序,它按递增顺序取一个整数数组,并按递增顺序将其拆分为k个非空数组,当组合成单个数组时会生成原始数组 - 第一个数组不能包含任何除第一个或多个数组之外的任何数组数字(k1 = [1,2,3]有效,但k1 = [2,3,4]不是)
到目前为止,我已经尝试过给array[4,7,11,21,31]
和k=3
硬编码两个for循环,它们作为指针复制项目的位置并将原始数组的一部分复制到受尊重的变量中
int[] array = {1,2,3,4,5};
int k = 3;
int n = 5;
for(int i = 0; i <= n - k; i++){
for(int j = i+1; j < n-1; j++){
int[] k1 = Arrays.copyOfRange(array , 0, i+1);
int[] k2 = Arrays.copyOfRange(array , i+1, j+1);
int[] k3 = Arrays.copyOfRange(array , j+1, n);
}
}
上面的代码适用于k=3
,但问题是我不知道如何有效地使它适用于任何k
并有效地存储数组
最终目标是生成所有可能的组合
这种递归的暴力方法并没有真正拆分数字数组,它只返回必须发生拆分的数组条目的索引。
它需要两个参数:
n
阵列的长度k
想要的零件数量它将返回包含所有可能的分裂组合的ArrayList<int[]>
(每个分组作为索引数组,其中k-1
元素按升序排列)。
我尝试了一些案例,似乎有效。正如预期的那样,似乎总是返回二项式系数(n-1) over (k-1)
的组合量。这是因为在任何长度为n
的数组中都有n-1
的位置,它可以分成两个。我们只想将它分开k-1
次(尽管最终得到k
部分)。所以这基本上是从k-1
中选择n-1
,因此是二项式系数。
public static ArrayList<int[]> getSplits(int n, int k) {
if (k == 1) {
return new ArrayList<int[]>();
}
ArrayList<int[]> newSplits = new ArrayList<int[]>();
for (int s = 1; s < n-(k-1)+1; s++) {
if (k == 2) {
newSplits.add(new int[] {s});
} else {
ArrayList<int[]> splits = getSplits(n-s, k-1);
for (int[] split : splits) {
int[] newSplit = new int[split.length + 1];
newSplit[0] = s;
for (int i = 0; i < split.length; i++) {
newSplit[i+1] = split[i] + s;
}
newSplits.add(newSplit);
}
}
}
return newSplits;
}
用于您的问题:
要从中获取阵列部件,可以使用此功能。它输出它们用管道符号(|
)分隔。
public static void main(String args[]) {
int[] array = new int[] {1, 2, 3, 4};
int n = array.length;
int k = 3;
ArrayList<int[]> splits = getSplits(n, k);
for (int[] split : splits) {
int j = 0;
for (int i = 0; i < split.length; i++) {
for (; j < split[i]; j++) {
System.out.print(array[j] + " ");
}
System.out.print("| ");
}
for (; j < n; j++) {
System.out.print(array[j] + " ");
}
System.out.println();
}
}
这将打印以下内容(所有可能将4个项目拆分为3个非空组):
1 | 2 | 3 4
1 | 2 3 | 4
1 2 | 3 | 4