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)
|
||||
* [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
|
||||
* [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - "Brute Force" and "Dynamic Programming" versions
|
||||
* **String**
|
||||
* [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
|
||||
@ -100,7 +101,7 @@
|
||||
* [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)
|
||||
* [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
|
||||
* **Backtracking**
|
||||
* **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