/** * A recursive divide-and-conquer solution to the Maximum Subset problem * * @author americachambers * */ public class Recursive implements SubsetIfc { public SubsetInfo solve(int[] array){ return recursive(array, 0, array.length-1); } /** * The main recursive method that divides the array * in half and then merges the solutions to subproblems to * construct a solution to the original problem * * @param array An array of integers * @param low Leftmost (or lowest) index into array * @param high Rightmost (or highest) index into array * @return Solution to the Subset Sum problem */ private SubsetInfo recursive(int[] array, int low, int high) { SubsetInfo s = new SubsetInfo(); // Base case is a single day if(low == high) { s.start = low; s.end = low; s.sum = array[low]; } else{ // Divide the problem just like we do in Mergesort int mid = (low+high)/2; SubsetInfo fromLeft= recursive(array, low, mid); SubsetInfo fromRight = recursive(array, mid+1, high); // Find the solution that spans the left and right subproblems SubsetInfo fromCross = findCross(array, low, mid, high); // Determine which solution is best: from the left, the right, or the solution // that spans the left and right subproblems if(fromLeft.sum > fromRight.sum && fromLeft.sum > fromCross.sum) { s.start = fromLeft.start; s.end = fromLeft.end; s.sum = fromLeft.sum; } else if(fromRight.sum > fromLeft.sum && fromRight.sum > fromCross.sum){ s.start = fromRight.start; s.end = fromRight.end; s.sum = fromRight.sum; } else{ s.start = fromCross.start; s.end = fromCross.end; s.sum = fromCross.sum; } } return s; } /** * This method finds the solution that crosses/spans the * two subproblems * * @param array Array of integers * @param low Leftmost (or lowest) index into array * @param mid Middle index into array * @param high Rightmost (or highest) index into array * @return Optimal solution that spans the two subproblems */ private SubsetInfo findCross(int[] array, int low, int mid, int high){ int left_sum = -10000; // yikes! never do this! int sum = 0; int max_left = 0; for(int i = mid; i >= low; i--){ sum += array[i]; if( sum > left_sum) { left_sum = sum; max_left = i; } } sum = 0; int right_sum = -10000; // yikes int max_right = 0; for(int j = mid+1; j <= high; j++) { sum += array[j]; if(sum > right_sum) { right_sum = sum; max_right = j; } } SubsetInfo s = new SubsetInfo(); s.start = max_left; s.end = max_right; s.sum = left_sum + right_sum; return s; } }