mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-25 14:26:09 +08:00
Add a Divide and Conquer version of the MaxSubArray problem.
This commit is contained in:
parent
819f38f792
commit
82f0b5edf0
@ -207,6 +207,7 @@ algorithm is an abstraction higher than a computer program.
|
||||
* `B` [Best Time To Buy Sell Stocks](src/algorithms/uncategorized/best-time-to-buy-sell-stocks) - divide and conquer and one-pass examples
|
||||
* `A` [Permutations](src/algorithms/sets/permutations) (with and without repetitions)
|
||||
* `A` [Combinations](src/algorithms/sets/combinations) (with and without repetitions)
|
||||
* `A` [Maximum Subarray](src/algorithms/sets/maximum-subarray)
|
||||
* **Dynamic Programming** - build up a solution using previously found sub-solutions
|
||||
* `B` [Fibonacci Number](src/algorithms/math/fibonacci)
|
||||
* `B` [Jump Game](src/algorithms/uncategorized/jump-game)
|
||||
@ -278,6 +279,8 @@ rm -rf ./node_modules
|
||||
npm i
|
||||
```
|
||||
|
||||
Also make sure that you're using a correct Node version (`>=14.16.0`). If you're using [nvm](https://github.com/nvm-sh/nvm) for Node version management you may run `nvm use` from the root folder of the project and the correct version will be picked up.
|
||||
|
||||
**Playground**
|
||||
|
||||
You may play with data-structures and algorithms in `./src/playground/playground.js` file and write
|
||||
|
@ -15,6 +15,12 @@ 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`.
|
||||
|
||||
## Solutions
|
||||
|
||||
- Brute Force solution `O(n^2)`: [bfMaximumSubarray.js](./bfMaximumSubarray.js)
|
||||
- Divide and Conquer solution `O(n^2)`: [dcMaximumSubarraySum.js](./dcMaximumSubarraySum.js)
|
||||
- Dynamic Programming solution `O(n)`: [dpMaximumSubarray.js](./dpMaximumSubarray.js)
|
||||
|
||||
## References
|
||||
|
||||
- [Wikipedia](https://en.wikipedia.org/wiki/Maximum_subarray_problem)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import bfMaximumSubarray from '../bfMaximumSubarray';
|
||||
|
||||
describe('bfMaximumSubarray', () => {
|
||||
it('should find maximum subarray using brute force algorithm', () => {
|
||||
it('should find maximum subarray using the brute force algorithm', () => {
|
||||
expect(bfMaximumSubarray([])).toEqual([]);
|
||||
expect(bfMaximumSubarray([0, 0])).toEqual([0]);
|
||||
expect(bfMaximumSubarray([0, 0, 1])).toEqual([0, 0, 1]);
|
||||
|
@ -0,0 +1,16 @@
|
||||
import dcMaximumSubarray from '../dcMaximumSubarraySum';
|
||||
|
||||
describe('dcMaximumSubarraySum', () => {
|
||||
it('should find maximum subarray sum using the divide and conquer algorithm', () => {
|
||||
expect(dcMaximumSubarray([])).toEqual(-Infinity);
|
||||
expect(dcMaximumSubarray([0, 0])).toEqual(0);
|
||||
expect(dcMaximumSubarray([0, 0, 1])).toEqual(1);
|
||||
expect(dcMaximumSubarray([0, 0, 1, 2])).toEqual(3);
|
||||
expect(dcMaximumSubarray([0, 0, -1, 2])).toEqual(2);
|
||||
expect(dcMaximumSubarray([-1, -2, -3, -4, -5])).toEqual(-1);
|
||||
expect(dcMaximumSubarray([1, 2, 3, 2, 3, 4, 5])).toEqual(20);
|
||||
expect(dcMaximumSubarray([-2, 1, -3, 4, -1, 2, 1, -5, 4])).toEqual(6);
|
||||
expect(dcMaximumSubarray([-2, -3, 4, -1, -2, 1, 5, -3])).toEqual(7);
|
||||
expect(dcMaximumSubarray([1, -3, 2, -5, 7, 6, -1, 4, 11, -23])).toEqual(27);
|
||||
});
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
import dpMaximumSubarray from '../dpMaximumSubarray';
|
||||
|
||||
describe('dpMaximumSubarray', () => {
|
||||
it('should find maximum subarray using dynamic programming algorithm', () => {
|
||||
it('should find maximum subarray using the dynamic programming algorithm', () => {
|
||||
expect(dpMaximumSubarray([])).toEqual([]);
|
||||
expect(dpMaximumSubarray([0, 0])).toEqual([0]);
|
||||
expect(dpMaximumSubarray([0, 0, 1])).toEqual([0, 0, 1]);
|
||||
|
33
src/algorithms/sets/maximum-subarray/dcMaximumSubarraySum.js
Normal file
33
src/algorithms/sets/maximum-subarray/dcMaximumSubarraySum.js
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Divide and Conquer solution.
|
||||
* Complexity: O(n^2) in case if no memoization applied
|
||||
*
|
||||
* @param {Number[]} inputArray
|
||||
* @return {Number[]}
|
||||
*/
|
||||
export default function dcMaximumSubarraySum(inputArray) {
|
||||
/**
|
||||
* We are going through the inputArray array and for each element we have two options:
|
||||
* - to pick
|
||||
* - not to pick
|
||||
*
|
||||
* Also keep in mind, that the maximum sub-array must be contiguous. It means if we picked
|
||||
* the element, we need to continue picking the next elements or stop counting the max sum.
|
||||
*
|
||||
* @param {number} elementIndex - the index of the element we're deciding to pick or not
|
||||
* @param {boolean} mustPick - to pick or not to pick the element
|
||||
* @returns {number} - maximum subarray sum that we'll get
|
||||
*/
|
||||
function solveRecursively(elementIndex, mustPick) {
|
||||
if (elementIndex >= inputArray.length) {
|
||||
return mustPick ? 0 : -Infinity;
|
||||
}
|
||||
return Math.max(
|
||||
// Option #1: Pick the current element, and continue picking next one.
|
||||
inputArray[elementIndex] + solveRecursively(elementIndex + 1, true),
|
||||
// Option #2: Don't pick the current element.
|
||||
mustPick ? 0 : solveRecursively(elementIndex + 1, false),
|
||||
);
|
||||
}
|
||||
return solveRecursively(0, false);
|
||||
}
|
Loading…
Reference in New Issue
Block a user