情景:
我有X个元素。我需要尽可能均匀地分割/分割这些元素,正好是Y次(不多)。应将任何余数添加到最后一个索引。
问题:执行此操作的最佳方式是什么
代码示例我尝试过
public static void main (String[] args){
Integer[] payload1 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
Integer[] payload2 = {0,1,2,3,4,5,6,7,8,9,10,11,12};
Integer[] payload3 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Integer[] payload4 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
Integer[] payload5 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
ArrayList<Integer[]> payloads = new ArrayList<Integer[]>();
payloads.add(payload1);
payloads.add(payload2);
payloads.add(payload3);
payloads.add(payload4);
payloads.add(payload5);
int splits = 5;
for(Integer[] x : payloads){
int counter = 1;
for(ArrayList<Integer> i : Segmenter.splitter(x, splits))
System.out.println(counter+++" "+i.toString()+" Size : "+i.size());
System.out.println("");
}
}
public static ArrayList<ArrayList<Integer>> splitter(Intger[] payload, int splits){
int distibution = (payload.length + splits - 1) / splits;
System.out.println("Distibution : "+distibution);
ArrayList<ArrayList<Integer>> assembledArray = new ArrayList<ArrayList<Integer>>();
int size = (payload.length + splits - 1) / splits;
for(int i = 0; i < payload.length; i++)
{
if(i % size == 0)
assembledArray.add(new ArrayList<Integer>());
assembledArray.get(i / size).add(payload[i]);
}
return assembledArray;
}
}
由于abagshaw&amp; amp; selbie
上方的结果
Steps : 5
1 [0, 1, 2, 3, 4]
2 [5, 6, 7, 8, 9]
3 [10, 11, 12, 13, 14]
4 [15, 16, 17, 18, 19]
5 [20, 21, 22, 23, 24]
Steps : 3
1 [0, 1, 2]
2 [3, 4, 5]
3 [6, 7, 8]
4 [9, 10, 11]
5 [12]
问题:请注意,应该有6个结果数组(因此splits = 6)。以上情况仅返回此边缘情况下的5个数组
欲望结果示例
当15个元素(加上第0个索引)需要拆分6次时
1 [0, 1, 2]
2 [3, 4, 5]
3 [6, 7, 8]
4 [9, 10, 11]
5 [12, 13, 14]
6 [15]
当12个元素(加上第0个索引)需要拆分6次时
1 [0, 1]
2 [2, 3]
3 [4, 5]
4 [6, 7]
5 [8, 9]
6 [10, 11, 12]
当11个元素(加上第0个索引)需要拆分6次时
1 [0, 1]
2 [2, 3]
3 [4, 5]
4 [6, 7]
5 [8, 9]
6 [10, 11]
当15个元素(加上第0个索引)需要拆分8次
时1 [0, 1]
2 [2, 3]
3 [4, 5]
4 [6, 7]
5 [8, 9]
6 [10, 11]
7 [12, 13]
8 [14, 15]
等等..
解决方案(感谢selbie)
答案 0 :(得分:3)
这是一个更直接的解决方案,有点清洁:
编辑:拆分器符合规则,其中拆分始终等于输出assembleArray.length,并且所有期望的结果都应该有效。
public static ArrayList<ArrayList<Integer>> splitter(int[] payload, int splits){
ArrayList<ArrayList<Integer>> assembledArray = new ArrayList<ArrayList<Integer>>();
int[] sizes = new int[splits];
int j = 0;
for(j = 0; j < payload.length; j++)
{
if(payload.length - j < splits && j % (splits - 1) == 0)
break;
sizes[splits - (j % (splits - 1)) - 2]++;
}
sizes[sizes.length - 1] = payload.length - j;
int currentOn = 0;
int currentIndex = 0;
for(int i = 0; i < payload.length; i++)
{
if(currentOn == 0)
{
assembledArray.add(new ArrayList<Integer>());
currentOn = sizes[currentIndex];
currentIndex++;
}
assembledArray.get(currentIndex - 1).add(payload[i]);
currentOn--;
}
return assembledArray;
}
答案 1 :(得分:1)
不要使用浮点(双精度)来计算steps
的值。替换此行:
int steps = (int) Math.ceil(payloadSize/(double)splits);
有了这个:
steps = payloadSize / splits;
然后你的for循环或多或少是你拥有的。这里有一些轻微的调整:
protected ArrayList<ArrayList<Integer>> splitter(int [] payload, int splits)
{
ArrayList<Integer> segment = null;
ArrayList<ArrayList<Integer>> assembledArray = new ArrayList<ArrayList<Integer>>();
int steps = payload.length / splits;
for(int i=0; i<payload.length; i++) {
if (segment == null) {
segment = new ArrayList<Integer>();
assembledArray.add(segment);
}
segment.add(payload[i]);
if ((segment.size()>=steps) && (assembledArray.size() < splits))
// null out the segment to indicate a new one must be created
// unless we are on the last split index
segment = null;
}
}
return assembledArray;