mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Add maximum subarray.
This commit is contained in:
parent
293b6f721f
commit
b128f20443
@ -42,6 +42,7 @@
|
|||||||
* [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
|
* [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
|
||||||
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS)
|
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS)
|
||||||
* [Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones
|
* [Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones
|
||||||
|
* [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - "Brute Force" and "Dynamic Programming" versions
|
||||||
* **String**
|
* **String**
|
||||||
* [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
|
* [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
|
||||||
* [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different
|
* [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 @@
|
|||||||
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence)
|
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence)
|
||||||
* [0/1 Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem)
|
* [0/1 Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem)
|
||||||
* [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition)
|
* [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition)
|
||||||
* Maximum subarray
|
* [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray)
|
||||||
* Maximum sum path
|
* Maximum sum path
|
||||||
* **Backtracking**
|
* **Backtracking**
|
||||||
* **Branch & Bound**
|
* **Branch & Bound**
|
||||||
|
19
src/algorithms/sets/maximum-subarray/README.md
Normal file
19
src/algorithms/sets/maximum-subarray/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Maximum subarray problem
|
||||||
|
|
||||||
|
The maximum subarray problem is the task of finding the contiguous
|
||||||
|
subarray within a one-dimensional array, `a[1...n]`, of numbers
|
||||||
|
which has the largest sum, where,
|
||||||
|
|
||||||
|
![Maximum subarray](https://wikimedia.org/api/rest_v1/media/math/render/svg/e8960f093107b71b21827e726e2bad8b023779b2)
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
The list usually contains both positive and negative numbers along
|
||||||
|
with `0`. For example, for the array of
|
||||||
|
values `−2, 1, −3, 4, −1, 2, 1, −5, 4` the contiguous subarray
|
||||||
|
with the largest sum is `4, −1, 2, 1`, with sum `6`.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Wikipedia](https://en.wikipedia.org/wiki/Maximum_subarray_problem)
|
||||||
|
- [YouTube](https://www.youtube.com/watch?v=ohHWQf1HDfU)
|
@ -0,0 +1,12 @@
|
|||||||
|
import bfMaximumSubarray from '../bfMaximumSubarray';
|
||||||
|
|
||||||
|
describe('bfMaximumSubarray', () => {
|
||||||
|
it('should find maximum subarray using brute force algorithm', () => {
|
||||||
|
expect(bfMaximumSubarray([])).toEqual([]);
|
||||||
|
expect(bfMaximumSubarray([-1, -2, -3, -4, -5])).toEqual([-1]);
|
||||||
|
expect(bfMaximumSubarray([1, 2, 3, 2, 3, 4, 5])).toEqual([1, 2, 3, 2, 3, 4, 5]);
|
||||||
|
expect(bfMaximumSubarray([-2, 1, -3, 4, -1, 2, 1, -5, 4])).toEqual([4, -1, 2, 1]);
|
||||||
|
expect(bfMaximumSubarray([-2, -3, 4, -1, -2, 1, 5, -3])).toEqual([4, -1, -2, 1, 5]);
|
||||||
|
expect(bfMaximumSubarray([1, -3, 2, -5, 7, 6, -1, 4, 11, -23])).toEqual([7, 6, -1, 4, 11]);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,12 @@
|
|||||||
|
import dpMaximumSubarray from '../dpMaximumSubarray';
|
||||||
|
|
||||||
|
describe('dpMaximumSubarray', () => {
|
||||||
|
it('should find maximum subarray using dynamic programming algorithm', () => {
|
||||||
|
expect(dpMaximumSubarray([])).toEqual([]);
|
||||||
|
expect(dpMaximumSubarray([-1, -2, -3, -4, -5])).toEqual([-1]);
|
||||||
|
expect(dpMaximumSubarray([1, 2, 3, 2, 3, 4, 5])).toEqual([1, 2, 3, 2, 3, 4, 5]);
|
||||||
|
expect(dpMaximumSubarray([-2, 1, -3, 4, -1, 2, 1, -5, 4])).toEqual([4, -1, 2, 1]);
|
||||||
|
expect(dpMaximumSubarray([-2, -3, 4, -1, -2, 1, 5, -3])).toEqual([4, -1, -2, 1, 5]);
|
||||||
|
expect(dpMaximumSubarray([1, -3, 2, -5, 7, 6, -1, 4, 11, -23])).toEqual([7, 6, -1, 4, 11]);
|
||||||
|
});
|
||||||
|
});
|
26
src/algorithms/sets/maximum-subarray/bfMaximumSubarray.js
Normal file
26
src/algorithms/sets/maximum-subarray/bfMaximumSubarray.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Brute Force solution.
|
||||||
|
* Complexity: O(n^2)
|
||||||
|
*
|
||||||
|
* @param {Number[]} inputArray
|
||||||
|
* @return {Number[]}
|
||||||
|
*/
|
||||||
|
export default function bfMaximumSubarray(inputArray) {
|
||||||
|
let maxSubarrayStartIndex = 0;
|
||||||
|
let maxSubarrayLength = 0;
|
||||||
|
let maxSubarraySum = null;
|
||||||
|
|
||||||
|
for (let startIndex = 0; startIndex < inputArray.length; startIndex += 1) {
|
||||||
|
let subarraySum = 0;
|
||||||
|
for (let arrLength = 1; arrLength <= (inputArray.length - startIndex); arrLength += 1) {
|
||||||
|
subarraySum += inputArray[startIndex + (arrLength - 1)];
|
||||||
|
if (maxSubarraySum === null || subarraySum > maxSubarraySum) {
|
||||||
|
maxSubarraySum = subarraySum;
|
||||||
|
maxSubarrayStartIndex = startIndex;
|
||||||
|
maxSubarrayLength = arrLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputArray.slice(maxSubarrayStartIndex, maxSubarrayStartIndex + maxSubarrayLength);
|
||||||
|
}
|
62
src/algorithms/sets/maximum-subarray/dpMaximumSubarray.js
Normal file
62
src/algorithms/sets/maximum-subarray/dpMaximumSubarray.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Dynamic Programming solution.
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highestElementValue === null || highestElementValue < inputArray[i]) {
|
||||||
|
highestElementValue = inputArray[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user