package com.interview.books.question300;
import com.interview.utils.ArrayUtil;
import com.interview.utils.ConsoleWriter;
import java.util.Arrays;
/**
* Created_By: stefanie
* Date: 14-7-28
* Time: 下午8:44
*
* Given an array, write code to divide the array into M sub array (find largest M), make sure the sum of all sub array are the same.
*
* Clue:
* 1. M should 1 <= M <= N
* 2. sum(array) mod M == 0
* Solution:
* 1. Loop on M, check if M conform to Clue 2
* 2. Find the M division, if could find a solution return m.
*
*/
public class TQ59_ArrayMDivision {
static class Division{
int M;
int[] groups;
public Division(int M, int[] groups){
this.M = M;
this.groups = groups;
}
}
public Division divide(int[] array){
int sum = ArrayUtil.sum(array, 0, array.length - 1);
int[] mark = new int[array.length];
for(int m = array.length; m >= 2; m--){
if(sum % m != 0) continue;
if(canDivide(array, sum, m, mark)) return new Division(m, mark);
}
Arrays.fill(mark, 1);
return new Division(1, mark);
}
private boolean canDivide(int[] array, int sum, int m, int[] mark){
int averageSum = sum / m;
Arrays.fill(mark, 0);
for(int i = 0; i < array.length; i++){ //if any array[i] > averageSum, can't be divided
if(array[i] > averageSum) return false;
}
for(int groupID = 1; groupID <= m; groupID++){ //try to divide M group
if(!canDivide(array, averageSum, groupID, mark, 0, 0)) return false;
}
return true;
}
private boolean canDivide(int[] array, int target, int groupID, int[] mark, int currentSum, int begin){
for(int i = begin; i < array.length; i++){
if(mark[i] == 0 && currentSum + array[i] <= target){
mark[i] = groupID;
if(currentSum + array[i] == target) return true;
else if(canDivide(array, target, groupID, mark, currentSum + array[i], i+1)) return true;
else mark[i] = 0;
}
}
return false;
}
public static void main(String[] args){
TQ59_ArrayMDivision divisor = new TQ59_ArrayMDivision();
int[] array = new int[] {2,3,4,6,3};
Division division = divisor.divide(array);
System.out.println(division.M); //3
ConsoleWriter.printIntArray(division.groups); //1, 2, 1, 3, 2,
array = new int[] {6,3,4,6,3};
division = divisor.divide(array);
System.out.println(division.M); //1
ConsoleWriter.printIntArray(division.groups); //1, 1, 1, 1, 1,
}
}