From 47dff8d93bd0f2eb9300900642c781acedc9ca3d Mon Sep 17 00:00:00 2001
From: Bruce Feldman <bfeldman@sunriselabs.com>
Date: Sat, 11 Aug 2018 18:05:54 -0400
Subject: [PATCH] Made maximum subarray solution more terse

---
 .../maximum-subarray/dpMaximumSubarray.js     | 61 +++----------------
 1 file changed, 9 insertions(+), 52 deletions(-)

diff --git a/src/algorithms/sets/maximum-subarray/dpMaximumSubarray.js b/src/algorithms/sets/maximum-subarray/dpMaximumSubarray.js
index 12f919d737..342e7f10e8 100644
--- a/src/algorithms/sets/maximum-subarray/dpMaximumSubarray.js
+++ b/src/algorithms/sets/maximum-subarray/dpMaximumSubarray.js
@@ -1,62 +1,19 @@
 /**
- * Dynamic Programming solution.
+ * Dynamic Programming solution using Kadane's algorithm.
  * Complexity: O(n)
  *
  * @param {Number[]} inputArray
  * @return {Number[]}
  */
 export default function dpMaximumSubarray(inputArray) {
-  // Check if all elements of inputArray are negative ones and return the highest
-  // one in this case.
-  let allNegative = true;
-  let highestElementValue = null;
-  for (let i = 0; i < inputArray.length; i += 1) {
-    if (inputArray[i] >= 0) {
-      allNegative = false;
-    }
+  // Use Kadane's algorithm to generate list of maximum sums ending/beginning at index.
+  const endMax = inputArray.reduce((a, x, i) => a.concat([x + Math.max(0, a[i - 1] || 0)]), []);
+  const begMax = inputArray.reduceRight((a, x) => [x + Math.max(0, a[0] || 0)].concat(a), []);
 
-    if (highestElementValue === null || highestElementValue < inputArray[i]) {
-      highestElementValue = inputArray[i];
-    }
-  }
+  // Obtain the maximum value for the sum of subarrays.
+  const maxVal = begMax.reduce((acc, val) => Math.max(acc, val), -Infinity);
 
-  if (allNegative && highestElementValue !== null) {
-    return [highestElementValue];
-  }
-
-  // Let's assume that there is at list one positive integer exists in array.
-  // And thus the maximum sum will for sure be grater then 0. Thus we're able
-  // to always reset max sum to zero.
-  let maxSum = 0;
-
-  // This array will keep a combination that gave the highest sum.
-  let maxSubArray = [];
-
-  // Current sum and subarray that will memoize all previous computations.
-  let currentSum = 0;
-  let currentSubArray = [];
-
-  for (let i = 0; i < inputArray.length; i += 1) {
-    // Let's add current element value to the current sum.
-    currentSum += inputArray[i];
-
-    if (currentSum < 0) {
-      // If the sum went below zero then reset it and don't add current element to max subarray.
-      currentSum = 0;
-      // Reset current subarray.
-      currentSubArray = [];
-    } else {
-      // If current sum stays positive then add current element to current sub array.
-      currentSubArray.push(inputArray[i]);
-
-      if (currentSum > maxSum) {
-        // If current sum became greater then max registered sum then update
-        // max sum and max subarray.
-        maxSum = currentSum;
-        maxSubArray = currentSubArray.slice();
-      }
-    }
-  }
-
-  return maxSubArray;
+  // Extract indices of maximum value from array & use them to slice input.
+  const maxCmp = val => (val === maxVal);
+  return inputArray.slice(begMax.findIndex(maxCmp), endMax.findIndex(maxCmp) + 1);
 }