Range of maximum product subarray (Kadane algorithm variant) - java

I have been trying to get the range of a Maximum Product of a subarray (studying for job interviews).
This has been already asked here (but no valid answers have been provided).
Getting range of max product subarray using Kadanes algorithm
The trick/algorithm is explained well here: http://www.geeksforgeeks.org/maximum-product-subarray/
I am able to get the maximum product easily, but after a lot of tries, still can't figure out how to get the range (left and right indexes properly). Can anyone please help??
I have pasted my code, so you can just copy and run it quickly..
import java.util.*;
public class ArrayMax {
// maximum product
public static int[] getMaxProduct(int[] list)
{
int max = 1, min = 1, maxProd = 0;
int l = 0, left = 0, right = 0;
for (int i = 0; i < list.length; i++) {
// positive number!
if (list[i] > 0) {
max = max * list[i];
min = Math.min(1, min * list[i]);
}
else if (list[i] == 0) {
max = 1; // reset all
min = 1;
l = i + 1;
}
else {
// hold the current Max
int tempMax = max;
// need to update left here (but how??)
max = Math.max(min * list[i], 1); // [-33, 3]
min = tempMax * list[i]; // update min with prev max
}
// System.out.printf("[%d %d]%n", max, min);
if (max >= maxProd) {
maxProd = max;
right = i;
left = l;
}
}
System.out.println("Max: " + maxProd);
// copy array
return Arrays.copyOfRange(list, left, right + 1);
}
// prints array
public static void printArray(int[] list) {
System.out.print("[");
for (int i = 0; i < list.length; i++) {
String sep = (i < list.length - 1) ? "," : "";
System.out.printf("%d%s", list[i], sep);
}
System.out.print("]");
}
public static void main(String[] args) {
int[][] list = {
{5, 1, -3, -8},
{0, 0, -11, -2, -3, 5},
{2, 1, -2, 9}
};
for (int i = 0; i < list.length; i++) {
int[] res = getMaxProduct(list[i]);
printArray(list[i]);
System.out.print(" => ");
printArray(res);
System.out.println();
}
}
}
Here are sample outputs:
Max: 120
[5,1,-3,-8] => [5,1,-3,-8]
Max: 30
[0,0,-11,-2,-3,5] => [-11,-2,-3,5]
Max: 9
[2,1,-2,9] => [2,1,-2,9]
As you can see, I am getting the maximum product, but the range is wrong.
Case#2, Max is 30 (correct answer: [-2,-3,5], showing: [-11,-2,-3,5])
Case#3, Max is 9 (correct answer: [9], giving: [2,1,-2,9])
Please help.

Easier way is to try to find left position/marker when you have calculated the maxProd (at the end). Your right position is accurate, so set left to right and divide maxProd by list[left] until you hit 1, while decrementing left. Thats when you have reached left.
The following code before the return should solve it.
int temp = maxProd;
left = right;
while (temp != 1) {
temp = temp / list[left--];
}
left++;
// copy array
return Arrays.copyOfRange(list, left, right + 1);

I think you need to keep track of 2 values for l. One will represent the start index for the subarray of numbers that multiply to make max, while the other will represent the start index for the subarray of numbers that multiply to make min.
However, an even easier way is to simply wait until you have found the maximum answer (in maxProd) and its position (in right). At this point you can then loop over the array multiplying the elements of the list until your total reaches maxProd (starting at right and iterating backwards). The last element you multiplied must be the start of the subarray.

Related

Find two numbers that have the maximum sum which is also an element in the array

I recently got this question in an interview:
Given an array find two numbers that have the maximum sum which is also an element in the array.
Input: 6 10 12 34 41 16
Output: 16
[Updated]My code below:
public class Solution {
public static int findMaximumNumbers(int a[])
{
Set<Integer> set=new HashSet<>();
for(int n:a) set.add(n);
Arrays.sort(a);
int max=Integer.MIN_VALUE;
for(int i=a.length-1;i>0;i--)
{
for(int j=i;j>=0;j--)
{
int sum = a[i] + a[j];
if(set.contains(sum) && max<sum)
max=sum;
}
}
return max;
}
public static void main(String[] args) {
System.out.println( findMaximumNumbers(new int[]{ 6, 10, 12, 34, 40, 16, 41, 47, 74 }));
System.out.println( findMaximumNumbers(new int[]{ 2, 25, 35, 40, 42, 60 }));
}
}
This algorithm takes O(n^2) time complexity. Does anyone have a better algorithm for this?
This is the fastest I could come up with. Since the list is sorted, you work backwards, attempting to find if any pair adds up to the maximum remaining in the array (the i loop). It will short circuit as fast as possible, with the correct answer. In the j loop, counting down stops when you reach a value less than half of the target (no use iterating remaining values that can't add up to the target). But I am hopeful someone can do better. The OP code will do n*(n-1)/2 iterations, but this one will always do less, even when there is no solution.
public static int findMaximumNumbers(int a[])
{
Set<Integer> set=new HashSet<>();
for(int n:a) set.add(n);
Arrays.sort(a);
if (a[0] == 0)
return a[a.length-1];
for(int i=a.length-1;i>0;i--)
{
int j = i-1;
int m = a[i] / 2;
while (j >= 0 && a[j] > m) {
if (set.contains(a[i]-a[j]))
return a[i];
j--;
}
}
return -1;
}
If your numbers are integers in the range 1 to M, then you can do this in O(Mlog(M)) by:
Computing a histogram of the values
Using the fast fourier transform to perform a convolution
searching for the biggest value present in the convolution
Example Python code:
import scipy.signal
import time
def hist(X):
"""Prepare a histogram of X"""
h = [0]*(max(X)+1)
for x in X:
h[x] += 1
return h
A = [6, 10, 12, 34, 41, 16]
H = hist(A)
R = scipy.signal.fftconvolve(H,H)
for x in sorted(A,reverse=True):
if R[x] > 0.5:
print x
break
else:
print 'No solutions'
The point is that the convolution of the histograms is the histogram of all possible sums of elements.
Of course, if you have 100 numbers with values in the range 1 to 10**100, then this would be less efficient than your O(n^2) algorithm so this is only useful if the values are limited.
If you sort the array first, you can just check pair by pair in ascending order, adding two consecutive numbers and checking if it is contained in the array.
int myArray[];
Arrays.sort(myArray);
int a = -1, b, highest = Integer.MIN_VALUE;
for(int i = 0; i < myArray.length - 1; i++)
{
int sum = myArray[i] + myArray[i + 1];
int startCheck = i + 1;
while(myArray[startCheck] < sum && startCheck < myArray.length)
startCheck++;
if(myArray[startCheck] == sum && sum > highest)
{
a = i;
b = i + 1;
highest = sum;
}
}
// Found 2 elements whose sum is on the array
if(a != -1)
{
}

How can I make an array without one number of the other array?

I am trying to make a code with two arrays. The second array has the same values of the first except for the smallest number. I have already made a code where z is the smallest number. Now I just want to make a new array without z, any feedback would be appreciated.
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
int i;
int z = ar[0];
for (i = 1; i < ar.length; i++) {
if (z >ar[i]) {
z=ar[i];
}
}
}
Java 8 streams have built in functionality that can achieve what you're wanting.
public static void main(String[] args) throws Exception {
int[] ar = {19, 1, 17, 17, -2, -2, -2, -2, 5};
// Find the smallest number
int min = Arrays.stream(ar)
.min()
.getAsInt();
// Make a new array without the smallest number
int[] newAr = Arrays
.stream(ar)
.filter(a -> a > min)
.toArray();
// Display the new array
System.out.println(Arrays.toString(newAr));
}
Results:
[19, 1, 17, 17, 5]
Otherwise, you'd be looking at something like:
public static void main(String[] args) throws Exception {
int[] ar = {19, 1, 17, 17, -2, -2, -2, -2, 5};
// Find the smallest number
// Count how many times the min number appears
int min = ar[0];
int minCount = 0;
for (int a : ar) {
if (minCount == 0 || a < min) {
min = a;
minCount = 1;
} else if (a == min) {
minCount++;
}
}
// Make a new array without the smallest number
int[] newAr = new int[ar.length - minCount];
int newIndex = 0;
for (int a : ar) {
if (a != min) {
newAr[newIndex] = a;
newIndex++;
}
}
// Display the new array
System.out.println(Arrays.toString(newAr));
}
Results:
[19, 1, 17, 17, 5]
I think the OP is on wrong track seeing his this comment:
"I am trying to find out the second smallest integer in array ar[]. I
should get an output of 1 once I am done. The way I want to achieve
that is by making a new array called newar[] and make it include all
the indexes of ar[], except without -2."
This is a very inefficient way to approach this problem. You'll have to do 3 passes, Once to find to smallest indexed element, another pass to remove the element (this is an array so removing an element will require a full pass), and another one to find smallest one again.
You should just do a single pass algorithm and keep track of the smallest two integers,
or even better use a tree for efficiency. Here are the best answers of this problem:
Find the 2nd largest element in an array with minimum number of comparisons
Algorithm: Find index of 2nd smallest element from an unknown array
UPDATE: Here is the algorithm with OP's requirements,
3 passes, and no external libraries:
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
//1st pass - find the smallest item on original array
int i;
int z = ar[0];
for (i = 1; i < ar.length; i++) {
if (z >ar[i]){
z=ar[i];
}
}
//2nd pass copy all items except smallest one to 2nd array
int[] ar2 = new int[ar.length-1];
int curIndex = 0;
for (i=0; i<ar.length; i++) {
if (ar[i]==z)
continue;
ar2[curIndex++] = ar[i];
}
//3rd pass - find the smallest item again
z = ar2[0];
for (i = 1; i < ar2.length; i++) {
if (z >ar2[i]){
z=ar2[i];
}
}
return z;
}
This grabs the index of the element specified in variable z and then sets a second array to the first array minus that one element.
Essentially this gives ar2 = ar1 minus element z
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
int[] ar2;
int i;
int z = ar[0];
int x = 0;
for (i = 1; i < ar.length; i++) {
if (z >ar[i]){
z=ar[i];
x=i;
}
}
ar2 = ArrayUtils.remove(ar, x);
return(z);
}

Sum of the maximum downsequence number in an array

Given this array
int [] myArray = {5,-11,2,3,14,5,-14,2};
You are to find the maximum sum of the values in any downsequence in an unsorted array of integers. If the array is of length zero then maxSeqValue must return Integer.MIN_VALUE.
You should print the number, 19 because the downsequence with the maximum sum is 14,5.
Downsequence number is a series of non-increasing number.
These are the codes that i used but i guess that there are some cases which is still not accounted for.
Any ideas, thanks in advance.
public class MaxDownSequence{
public int maxSeqValue(int[] a){
int sum=Integer.MIN_VALUE;
int maxsum=Integer.MIN_VALUE;
for (int i=1;i<a.length;i++){
if(a[i]<a[i-1]){
sum = a[i] + a[i-1];
if (sum>maxsum){
maxsum=sum;
}
}
else {
sum=a[i];
if (sum>maxsum){
maxsum=sum;
}
}
}
if (a.length==0){
return Integer.MIN_VALUE;
}
else{
return maxsum;
}
}
public static void main(String args[]){
MaxDownSequence mySeq = new MaxDownSequence();
int [] myArray = {5,-11,2,3,14,5,-14,2};
System.out.println(mySeq.maxSeqValue(myArray));
}
}
Take the input {3,2,1} the answer should be 6 your program gives 5.
Your approach is correct, every time you test a number in the array you check if its less than (actually this should be <=) previous array element.
If it is you update sum as: sum = a[i] + a[i-1]; this is incorrect. sum in your program represents the running rum of the current subsequence. You should not be overwriting it.
Dynamic programming is the way to go.
http://en.wikipedia.org/wiki/Dynamic_programming
I know, maybe that doesn't help at all, but since I don't want to post a solution for your problem the best thing I can do is to give you this hint :)
you haven't considered sequences of more than two numbers. If you had [3,2,1] the result should be 6. But your code would give 5, because it only looks at the sum of the current number and the previous, whereas you should keep track of a current downsequence and add the current number to the running total of that downsequence. Once you hit a number that breaks the downsequence update maxsum if needed then reset the running total to 0.
not sure why you have the else in the loop?? If a[i] is not less than a[i-1] then it is not a downsequence, therefore surely maxsum should not be updated. If you take just the first 3 numbers in your sample array, it would return the number 2. Because the first downsequence [5,-11] would give a sum of -6 and on the next iteration it would just look at 2, which is greater than -6 and therefore maxsum is updated.
No need for:
if (a.length==0){
return Integer.MIN_VALUE;
}
if the array length is 0 then you never enter the loop and therefore never change maxsum, so it will still be equal to Integer.MIN_VALUE, so you can just return maxsum at the end regardless.
You are suppose to have a running sum i think. Meaning Sum = Sum + A[i]. Just make sure to initialize the sum to the first member of the array and you are in business.
package sree;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.NestingKind;
public class MaximumSumSequence {
private final int[] theArray;
private MaximumSumSequence(int[] theArray) {
this.theArray = theArray;
}
private void maximumSequence() {
int currentMax = 0,currentSum = 0, start = 0, end = 0, nextStart = 0;
for (int i=0; i< theArray.length; i++) {
currentSum += theArray[ i ];
if (currentMax < currentSum) {
currentMax = currentSum;
start = nextStart;
nextStart = end;
end = i;
} else if (currentSum < 0) {
currentSum = 0;
}
}
System.out.println("Max Sum :" + currentMax);
System.out.println("Start :" + start);
System.out.println("End :" + end);
}
public static void main(String[] args) {
//int[] anArray = {4, -1, 2, -2, -1, -3};
int[] anArray ={-2, 1, -3, 4, -1, 2, 1, -5, 4};
new MaximumSumSequence(anArray).maximumSequence();
}
}

What's wrong with my Dutch National Flag algorithm?

I'm trying to turn an array like this:
0, 1, 2, 2, 1, 0, 1, 0, 0, 1, 2
into this:
0 0 0 0 1 1 1 1 2 2 2
Here is my code:
public static int[] sortDNF(int[] tape) {
int smaller = 0; // everything with index < smaller is 0
int bigger = tape.length - 1; // everything with index > bigger is 2
int current = 0; // where we are looking now
int tmp;
while (current <= bigger) {
if (tape[current] == 0) {
tmp = tape[smaller];
tape[smaller] = tape[current];
tape[current] = tmp;
smaller++;
}
if (tape[current] == 2) {
tmp = tape[bigger];
tape[bigger] = tape[current];
tape[current] = tmp;
bigger--;
}
current++;
}
return tape;
}
This is what it produces:
0 0 0 1 1 1 1 0 2 2 2
What is my problem?
A guess:
You should not be increasing current every time through the loop since that is supposed to represent the partition between the 1's and the unknowns. For example, when you hit the first 2 you end up swapping it with another 2 and then moving on. The fact that the 2 later gets swapped for a 0 is accidental. The elements between smaller and current should always be 1's and that is broken.
current++ should only be done in the tape[current] != 2 case. It's ok to do it when tape[current] = 0 because you haven't changed the [smaller -> current] = 1-only condition. And it's ok to move it when tape[current] = 1 because that satisfies the 1-only condition.
...but I haven't tried it.
For those who haven't studied the problem, sorting is sufficient to provide a solution, but it is (or can be) more than necessary. Solving the DNF problem only requires that all like items be moved together, but you don't have to place unequal items in any particular order.
It's pretty easy to solve DNF with expected O(N) complexity, where (most normal forms of) sorting have O(N lg N) complexity. Instead of rearranging the input elements, it's much easier to simply count the elements with any given value, then print out the right number of each. Since the order of unequal elements doesn't matter, you normally store your counts in a hash table.
The problem is that you reply on (possible nonexistent) values later in the chain to swap incorrectly skipped 1 values, try your algo on the trivial case of:
1 2 0
the 2 gets swapped in the right spot, but the current index has been advanced over the index 0 ends up in resulting in:
1 0 2
So don't increment current before you inspect the new value at that index.
You need to increment current only during the check for 1 and check for 2. When you are checking for 3 you just need to decrement bigger. Here the working solution. BTW this works for the array of values between 1-3. You can change it to 0-2 if you so wish.
The program produces the following output given a random number array as follows:
Original Array : [1, 3, 3, 3, 2, 2, 2, 1, 2, 2, 1, 3, 3, 2, 1, 1, 3]
Sorted Array : [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3]
private static int[] sortUsingDutchNationalFlagProblem(int[] array)
{
System.out.println("Original Array : " + Arrays.toString(array));
int smaller = 0; // everything with index < smaller is 1
int bigger = array.length - 1; // everything with index > bigger is 3
int current = 0; // where we are looking now
int tmp;
while (current <= bigger) {
if (array[current] == 1) {
tmp = array[smaller];
array[smaller] = array[current];
array[current] = tmp;
smaller++;current++;
}
if(array[current] == 2)
current++;
if (array[current] == 3) {
tmp = array[bigger];
array[bigger] = array[current];
array[current] = tmp;
bigger--;
}
}
System.out.println("Sorted Array : " + Arrays.toString(array));
return array;
}
Here is my approach using Java
public static void dutchNationalFlagProblem(int[] input) {
int low=0, mid=0, high = input.length -1;
while(mid <=high) {
switch (input[mid]) {
case 0:
swap(input, low++, mid++);
break;
case 1:
mid++;
break;
default :
swap(input, mid, high--);
break;
}
}
}
private static void swap(int[] input, int firstIndex, int secondIndex) {
int temp = input[firstIndex];
input[firstIndex] = input[secondIndex];
input[secondIndex] = temp;
}
Here is the corresponding test cases
#Test
public void dutchNationalFlagProblemTest() {
int[] input = new int[]{0,1,0,2,2,1};
ArrayUtils.dutchNationalFlagProblem(input);
assertThat(input, equalTo(new int[]{0,0,1,1,2,2}));
}
I'm going to propose an easier solution :-)
public static int[] sortDNF(int[] tape) {
Arrays.sort(tape);
return tape;
}
As far as what's wrong with your solution, when the current element is 2 and it's swapped with the element near the end of the list, the element it's swapped with may not be 2, but you're incrementing current and not looking at this position again.
public static int[] sortDNF(int[] tape) {
int smaller = 0; // everything with index < smaller is 0
int bigger = tape.length - 1; // everything with index > bigger is 2
int current = 0; // where we are looking now
int tmp;
while (current <= bigger) {
if (tape[current] == 0) {
tmp = tape[smaller];
tape[smaller] = tape[current];
tape[current] = tmp;
smaller++;
}
else if (tape[current] == 2) {
tmp = tape[bigger];
tape[bigger] = tape[current];
tape[current] = tmp;
bigger--;
}
current++;
}
return tape;
}
Below program is giving right result, do you guys see any issue in this simple innocent programming approach?
public class Test {
public static void main(String[] args) {
int arr[] = {1, 2, 0, 2, 1, 1, 1, 0, 0, 2, 2, 1, 0, 1, 2, 0, 2};
int x0 = 0, x1 = 0, x2 = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0)
x0++;
if (arr[i] == 1)
x1++;
if (arr[i] == 2)
x2++;
}
int i = 0;
for (int j = i; j < x0; j++)
arr[i++] = 0;
for (int j = i; j < x0+x1; j++)
arr[i++] = 1;
for (int j = i; j < x0+x1+x2; j++)
arr[i++] = 2;
printArray(arr);
}
private static void printArray(int[] arr) {
for (int a : arr) {
System.out.print(a + " ");
}
}
}

How do I divide an ordered list of integers into evenly sized sublists?

Does anyone have a good algorithm for taking an ordered list of integers, i.e.:
[1, 3, 6, 7, 8, 10, 11, 13, 14, 17, 19, 23, 25, 27, 28]
into a given number of evenly sized ordered sublists, i.e. for 4 it will be:
[1, 3, 6] [7, 8, 10, 11] [13, 14, 17, 19] [23, 25, 27, 28]
The requirement being that each of the sublists are ordered and as similar in size as possible.
Splitting the lists evenly means you will have two sizes of lists - size S and S+1.
With N sublists, and X elements in the original, you would get:
floor(X/N) number of elements in the smaller sublists (S), and X % N is the number of larger sublists (S+1).
Then iterate over the original array, and (looking at your example) creating small lists firsts.
Something like this maybe:
private static List<Integer[]> splitOrderedDurationsIntoIntervals(Integer[] durations, int numberOfIntervals) {
int sizeOfSmallSublists = durations.length / numberOfIntervals;
int sizeOfLargeSublists = sizeOfSmallSublists + 1;
int numberOfLargeSublists = durations.length % numberOfIntervals;
int numberOfSmallSublists = numberOfIntervals - numberOfLargeSublists;
List<Integer[]> sublists = new ArrayList(numberOfIntervals);
int numberOfElementsHandled = 0;
for (int i = 0; i < numberOfIntervals; i++) {
int size = i < numberOfSmallSublists ? sizeOfSmallSublists : sizeOfLargeSublists;
Integer[] sublist = new Integer[size];
System.arraycopy(durations, numberOfElementsHandled, sublist, 0, size);
sublists.add(sublist);
numberOfElementsHandled += size;
}
return sublists;
}
Here is my own recursive solution, inspired by merge sort and breadth first tree traversal:
private static void splitOrderedDurationsIntoIntervals(Integer[] durations, List<Integer[]> intervals, int numberOfInterals) {
int middle = durations.length / 2;
Integer[] lowerHalf = Arrays.copyOfRange(durations, 0, middle);
Integer[] upperHalf = Arrays.copyOfRange(durations, middle, durations.length);
if (lowerHalf.length > upperHalf.length) {
intervals.add(lowerHalf);
intervals.add(upperHalf);
} else {
intervals.add(upperHalf);
intervals.add(lowerHalf);
}
if (intervals.size() < numberOfIntervals) {
int largestElementLength = intervals.get(0).length;
if (largestElementLength > 1) {
Integer[] duration = intervals.remove(0);
splitOrderedDurationsIntoIntervals(duration, intervals);
}
}
}
I was hoping someone might have a suggestion for an iterative solution.
Here's a solution for Python. You can translate it to Java, you need a way to get a piece of of a list and then to return it. You cannot use the generator approach though, but you can append each sublist to a new list.
pseudocode...
private static void splitOrderedDurationsIntoIntervals(Integer[] durations, List<Integer[]> intervals, int numberOfInterals) {
int num_per_interval = Math.floor(durations.length / numberOfInterals);
int i;
int idx;
// make sure you have somewhere to put the results
for (i = 0; i < numberOfInterals; i++) intervals[i] = new Integer[];
// run once through the list and put them in the right sub-list
for (i = 0; i < durations.length; i++)
{
idx = Math.floor(i / num_per_interval);
intervals[idx].add(durations[i]);
}
}
That code will need a bit of tidying up, but I'm sure you get the point. Also I suspect that the uneven sized interval list will be at the end rather than at the beginning. If you really want it that way round you can probably do that by reversing the order of the loop.
That should be an Answer in a more iterative fashion.
public static void splitList(List<Integer> startList, List<List<Integer>> resultList,
int subListNumber) {
final int subListSize = startList.size() / subListNumber;
int index = 0;
int stopIndex = subListSize;
for (int i = subListNumber; i > 0; i--) {
resultList.add(new ArrayList<Integer>(startList.subList(index, stopIndex)));
index = stopIndex;
stopIndex =
(index + subListSize > startList.size()) ? startList.size() : index + subListSize;
}
}
You might consider something like this:
public static int[][] divide(int[] initialList, int sublistCount)
{
if (initialList == null)
throw new NullPointerException("initialList");
if (sublistCount < 1)
throw new IllegalArgumentException("sublistCount must be greater than 0.");
// without remainder, length / # lists will always be the minimum
// number of items in a given subset
int min = initialList.length / sublistCount;
// without remainer, this algorithm determines the maximum number
// of items in a given subset. example: in a 15-item sample,
// with 4 subsets, we get a min of 3 (15 / 4 = 3r3), and
// 15 + 3 - 1 = 17. 17 / 4 = 4r1.
// in a 16-item sample, min = 4, and 16 + 4 - 1 = 19. 19 / 4 = 4r3.
// The -1 is required in samples in which the max and min are the same.
int max = (initialList.length + min - 1) / sublistCount;
// this is the meat and potatoes of the algorithm. here we determine
// how many lists have the min count and the max count. we start out
// with all at max and work our way down.
int sublistsHandledByMax = sublistCount;
int sublistsHandledByMin = 0;
while ((sublistsHandledByMax * max) + (sublistsHandledByMin * min)
!= initialList.length)
{
sublistsHandledByMax--;
sublistsHandledByMin++;
}
// now we copy the items into their new sublists.
int[][] items = new int[sublistCount][];
int currentInputIndex = 0;
for (int listIndex = 0; listIndex < sublistCount; listIndex++)
{
if (listIndex < sublistsHandledByMin)
items[listIndex] = new int[min];
else
items[listIndex] = new int[max];
// there's probably a better way to do array copies now.
// it's been a while since I did Java :)
System.arraycopy(initialList, currentInputIndex, items[listIndex], 0, items[listIndex].length);
currentInputIndex += items[listIndex].length;
}
return items;
}
This isn't quite polished - I got into an infinite loop (I think) when I tried to pass an 18-item array in with 10 sublists. I think the algorithm breaks down when min == 1.
This should be fairly fast. Good luck :)

Categories