/** * A recursive divide-and-conquer solution to the transformed * Stock Market problem. The problem is transformed into an * instance of the Maximum subarray problem. * * @author americachambers * */ public class Transformation implements StockIfc { public static void main(String[] args) { Transformation t = new Transformation(); StockInfo solution = t.solve(null); System.out.println(solution); } public StockInfo solve(int[] prices){ int numDays = prices.length; int[] change = new int[numDays-1]; // Transform the problem into an instance of the // Maximum subarray problem for(int i = 0; i < change.length; i++) { change[i] = prices[i+1]-prices[i]; } return recursive(change, 0, change.length-1); } /** * The main recursive method that divides the price array * in half and then merges the solutions to subproblems to * construct a solution to the original problem * * @param change array of changes in stock price * @param low leftmost (or lowest) index into array * @param high rightmost (or highest) index into array * @return solution to the transformed Stock Market problem */ private StockInfo recursive(int[] change, int low, int high) { StockInfo s = new StockInfo(); // Base case is a single day if(low == high) { s.min_index = low; s.max_index = low; s.profit = change[low]; System.out.println("Base case: " + s); } else{ // Divide the problem just like we do in Mergesort int mid = (low+high)/2; StockInfo fromLeft= recursive(change, low, mid); StockInfo fromRight = recursive(change, mid+1, high); // Find the solution that spans the left and right subproblems StockInfo fromCross = findCross(change, low, mid, high); System.out.println("Left: " + fromLeft); System.out.println("Right: " + fromRight); System.out.println("Cross: " + fromCross); // Determine which solution is best: from the left, the right, or the solution // that spans the left and right subproblems if(fromLeft.profit > fromRight.profit && fromLeft.profit > fromCross.profit) { s.min_index = fromLeft.min_index; s.max_index = fromLeft.max_index; s.profit = fromLeft.profit; } else if(fromRight.profit > fromLeft.profit && fromRight.profit > fromCross.profit){ s.min_index = fromRight.min_index; s.max_index = fromRight.max_index; s.profit = fromRight.profit; } else{ s.min_index = fromCross.min_index; s.max_index = fromCross.max_index; s.profit = fromCross.profit; } } return s; } /** * This method finds the solution that crosses/spans the * two subproblems * * @param change array of changes in stock price * @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 StockInfo findCross(int[] change, 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 += change[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 += change[j]; if(sum > right_sum) { right_sum = sum; max_right = j; } } StockInfo s = new StockInfo(); s.min_index = max_left; s.max_index = max_right; s.profit = left_sum + right_sum; return s; } }