Skip to content

Commit b128f20

Browse files
committedMay 1, 2018
Add maximum subarray.
1 parent 293b6f7 commit b128f20

File tree

6 files changed

+133
-1
lines changed

6 files changed

+133
-1
lines changed
 

‎README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
* [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
4343
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS)
4444
* [Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones
45+
* [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - "Brute Force" and "Dynamic Programming" versions
4546
* **String**
4647
* [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
4748
* [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different
@@ -100,7 +101,7 @@
100101
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence)
101102
* [0/1 Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem)
102103
* [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition)
103-
* Maximum subarray
104+
* [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray)
104105
* Maximum sum path
105106
* **Backtracking**
106107
* **Branch & Bound**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Maximum subarray problem
2+
3+
The maximum subarray problem is the task of finding the contiguous
4+
subarray within a one-dimensional array, `a[1...n]`, of numbers
5+
which has the largest sum, where,
6+
7+
![Maximum subarray](https://wikimedia.org/api/rest_v1/media/math/render/svg/e8960f093107b71b21827e726e2bad8b023779b2)
8+
9+
## Example
10+
11+
The list usually contains both positive and negative numbers along
12+
with `0`. For example, for the array of
13+
values `−2, 1, −3, 4, −1, 2, 1, −5, 4` the contiguous subarray
14+
with the largest sum is `4, −1, 2, 1`, with sum `6`.
15+
16+
## References
17+
18+
- [Wikipedia](https://en.wikipedia.org/wiki/Maximum_subarray_problem)
19+
- [YouTube](https://www.youtube.com/watch?v=ohHWQf1HDfU)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import bfMaximumSubarray from '../bfMaximumSubarray';
2+
3+
describe('bfMaximumSubarray', () => {
4+
it('should find maximum subarray using brute force algorithm', () => {
5+
expect(bfMaximumSubarray([])).toEqual([]);
6+
expect(bfMaximumSubarray([-1, -2, -3, -4, -5])).toEqual([-1]);
7+
expect(bfMaximumSubarray([1, 2, 3, 2, 3, 4, 5])).toEqual([1, 2, 3, 2, 3, 4, 5]);
8+
expect(bfMaximumSubarray([-2, 1, -3, 4, -1, 2, 1, -5, 4])).toEqual([4, -1, 2, 1]);
9+
expect(bfMaximumSubarray([-2, -3, 4, -1, -2, 1, 5, -3])).toEqual([4, -1, -2, 1, 5]);
10+
expect(bfMaximumSubarray([1, -3, 2, -5, 7, 6, -1, 4, 11, -23])).toEqual([7, 6, -1, 4, 11]);
11+
});
12+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import dpMaximumSubarray from '../dpMaximumSubarray';
2+
3+
describe('dpMaximumSubarray', () => {
4+
it('should find maximum subarray using dynamic programming algorithm', () => {
5+
expect(dpMaximumSubarray([])).toEqual([]);
6+
expect(dpMaximumSubarray([-1, -2, -3, -4, -5])).toEqual([-1]);
7+
expect(dpMaximumSubarray([1, 2, 3, 2, 3, 4, 5])).toEqual([1, 2, 3, 2, 3, 4, 5]);
8+
expect(dpMaximumSubarray([-2, 1, -3, 4, -1, 2, 1, -5, 4])).toEqual([4, -1, 2, 1]);
9+
expect(dpMaximumSubarray([-2, -3, 4, -1, -2, 1, 5, -3])).toEqual([4, -1, -2, 1, 5]);
10+
expect(dpMaximumSubarray([1, -3, 2, -5, 7, 6, -1, 4, 11, -23])).toEqual([7, 6, -1, 4, 11]);
11+
});
12+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Brute Force solution.
3+
* Complexity: O(n^2)
4+
*
5+
* @param {Number[]} inputArray
6+
* @return {Number[]}
7+
*/
8+
export default function bfMaximumSubarray(inputArray) {
9+
let maxSubarrayStartIndex = 0;
10+
let maxSubarrayLength = 0;
11+
let maxSubarraySum = null;
12+
13+
for (let startIndex = 0; startIndex < inputArray.length; startIndex += 1) {
14+
let subarraySum = 0;
15+
for (let arrLength = 1; arrLength <= (inputArray.length - startIndex); arrLength += 1) {
16+
subarraySum += inputArray[startIndex + (arrLength - 1)];
17+
if (maxSubarraySum === null || subarraySum > maxSubarraySum) {
18+
maxSubarraySum = subarraySum;
19+
maxSubarrayStartIndex = startIndex;
20+
maxSubarrayLength = arrLength;
21+
}
22+
}
23+
}
24+
25+
return inputArray.slice(maxSubarrayStartIndex, maxSubarrayStartIndex + maxSubarrayLength);
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Dynamic Programming solution.
3+
* Complexity: O(n)
4+
*
5+
* @param {Number[]} inputArray
6+
* @return {Number[]}
7+
*/
8+
export default function dpMaximumSubarray(inputArray) {
9+
// Check if all elements of inputArray are negative ones and return the highest
10+
// one in this case.
11+
let allNegative = true;
12+
let highestElementValue = null;
13+
for (let i = 0; i < inputArray.length; i += 1) {
14+
if (inputArray[i] >= 0) {
15+
allNegative = false;
16+
}
17+
18+
if (highestElementValue === null || highestElementValue < inputArray[i]) {
19+
highestElementValue = inputArray[i];
20+
}
21+
}
22+
23+
if (allNegative && highestElementValue !== null) {
24+
return [highestElementValue];
25+
}
26+
27+
// Let's assume that there is at list one positive integer exists in array.
28+
// And thus the maximum sum will for sure be grater then 0. Thus we're able
29+
// to always reset max sum to zero.
30+
let maxSum = 0;
31+
32+
// This array will keep a combination that gave the highest sum.
33+
let maxSubArray = [];
34+
35+
// Current sum and subarray that will memoize all previous computations.
36+
let currentSum = 0;
37+
let currentSubArray = [];
38+
39+
for (let i = 0; i < inputArray.length; i += 1) {
40+
// Let's add current element value to the current sum.
41+
currentSum += inputArray[i];
42+
43+
if (currentSum < 0) {
44+
// If the sum went below zero then reset it and don't add current element to max subarray.
45+
currentSum = 0;
46+
// Reset current subarray.
47+
currentSubArray = [];
48+
} else {
49+
// If current sum stays positive then add current element to current sub array.
50+
currentSubArray.push(inputArray[i]);
51+
52+
if (currentSum > maxSum) {
53+
// If current sum became greater then max registered sum then update
54+
// max sum and max subarray.
55+
maxSum = currentSum;
56+
maxSubArray = currentSubArray.slice();
57+
}
58+
}
59+
}
60+
61+
return maxSubArray;
62+
}

0 commit comments

Comments
 (0)
Please sign in to comment.