Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to divide an array into 3 parts with the sum of each part roughly equal

Tags:

c#

algorithm

I have an arranged array and I want to divide it into 3 parts so that their sum are closest to each other.

Ex: I have this array:

    10, 8, 8, 7, 6, 6, 6, 5

so it'll be divided into 3 part like:

    p1 {10,8} sum = 18
    p2 {8,7,6} sum = 21
    p3 {6,6,5} sum = 17

like image 875
hienvd Avatar asked Nov 28 '11 07:11

hienvd


People also ask

How do you divide an array into 3 parts?

An efficient solution is to first find the sum S of all array elements. Check if this sum is divisible by 3 or not. This is because if sum is not divisible then the sum cannot be split in three equal sum sets. If there are three contiguous subarrays with equal sum, then sum of each subarray is S/3.

How do you split an array into equal parts?

To divide an array into two, we need at least three array variables. We shall take an array with continuous numbers and then shall store the values of it into two different variables based on even and odd values.

Can an array be divided into two subsequences with equal sums?

The array cannot be divided into 2 arrays of an equal sum.


4 Answers

The original poster already has a working solution (noted in comments) to split the array into two parts with equal sums; call this split2. The three-part version can be constructed using split2.

  1. Add to the array a new number equal to one-third of the sum of the original numbers.
  2. Split the array into two parts using split2.
  3. One part has the number that was added; remove it.
  4. Split the other part into two using split2.
like image 141
Michael J. Barber Avatar answered Sep 28 '22 21:09

Michael J. Barber


This is like two-Partition problem which is NP-Hard but not in strong sense, you can have an O(nK) algorithm for it where K is size of your input sum, See pseudo polynomial time algorithm for subset sum, Also See my answer for divide-list-in-two-parts-that-their-sum-closest-to-each-other, but in your case you should just add another dimension to process it.

like image 45
Saeed Amiri Avatar answered Sep 28 '22 23:09

Saeed Amiri


// calculate total
total = 0;
for(i = 0; i != size; ++i) {
   total += array[i];
}

// partition
n_partitions = 3;
current_partition = 1;
subtotal = array[0];
for(i = 1; i != size; ++i) {
   if(subtotal + array[i] > total / n_partitions) {
      // start new partition;
      current_partition++;
      subtotal = array[i];
   } else {
      // push to current partition
      subtotal += array[i];
   }
}
like image 32
Giovanni Funchal Avatar answered Sep 28 '22 22:09

Giovanni Funchal


Try the following code

int total = 0, partSum = 0, partIndex = 0;
int noOfParts = 3; //Initialize the no. of parts
int[] input = { 10, 8, 8, 7, 6, 6, 6, 5 };
int[] result = new int[noOfParts]; //Initialize result array with no. of locations equal to no. of parts, to store partSums
foreach (int i in input) //Calculate the total of input array values
{
    total += i;
}
int threshold = (total / noOfParts) - (total / input.Length) / 2; //Calculate a minimum threshold value for partSum
for (int j = input.Length - 1; j > -1; j--)
{
    partSum += input[j]; //Add array values to partSum incrementally
    if (partSum >= threshold) //If partSum reaches the threshold value, add it to result[] and reset partSum  
    {
        result[partIndex] = partSum;
        partIndex += 1;
        partSum = 0;
        continue;
    }
}
if (partIndex < noOfParts) //If no. of parts in result[] is less than the no. of parts required, add the remaining partSum value
{
    result[partIndex] = partSum;
}
Array.Reverse(result);
foreach (int k in result)
{
    Console.WriteLine(k);
}
Console.Read();     

I've tested this with various values in array(arranged in descending order) and also with different value for no. of parts(3,4,5...) and got good results.

like image 39
giftcv Avatar answered Sep 28 '22 23:09

giftcv