diff --git a/Data-Structures/Array/NumberOfLocalMaximumPoints.js b/Data-Structures/Array/NumberOfLocalMaximumPoints.js new file mode 100644 index 000000000..a61cd05ac --- /dev/null +++ b/Data-Structures/Array/NumberOfLocalMaximumPoints.js @@ -0,0 +1,42 @@ +/** + * [NumberOfLocalMaximumPoints](https://www.geeksforgeeks.org/find-indices-of-all-local-maxima-and-local-minima-in-an-array/) is an algorithm to find relative bigger numbers compared to their neighbors + * + * Notes: + * - like the other similar local maxima search function find relative maxima points in array but doesnt stop at one but returns total point count + * - runs on array A of size n and returns the local maxima count using divide and conquer methodology + * + * @complexity: O(n) (on average ) + * @complexity: O(n) (worst case) + * @flow + */ + +// check if returned index is a local maxima +const IsMaximumPoint = (array, index) => { + // handle array bounds + // array start + if (index === 0) { + return array[index] > array[index + 1] + // array end + } else if (index === array.length - 1) { + return array[index] > array[index - 1] + // handle index inside array bounds + } else { + return array[index] > array[index + 1] && array[index] > array[index - 1] + } +} + +const CountLocalMaximumPoints = (array, startIndex, endIndex) => { + // stop check in divide and conquer recursion + if (startIndex === endIndex) { + return IsMaximumPoint(array, startIndex) ? 1 : 0 + } + + // handle the two halves + const middleIndex = parseInt((startIndex + endIndex) / 2) + return CountLocalMaximumPoints(array, startIndex, middleIndex) + + CountLocalMaximumPoints(array, middleIndex + 1, endIndex) +} + +const NumberOfLocalMaximumPoints = (A) => CountLocalMaximumPoints(A, 0, A.length - 1) + +export { NumberOfLocalMaximumPoints } diff --git a/Data-Structures/Array/test/NumberOfLocalMaximumPoints.test.js b/Data-Structures/Array/test/NumberOfLocalMaximumPoints.test.js new file mode 100644 index 000000000..50edda64b --- /dev/null +++ b/Data-Structures/Array/test/NumberOfLocalMaximumPoints.test.js @@ -0,0 +1,43 @@ +import { NumberOfLocalMaximumPoints } from '../NumberOfLocalMaximumPoints' + +describe('LocalMaximomPoint tests', () => { + it('test boundry maximom points - last element', () => { + const Array = [1, 2, 3, 4, 5, 6, 12] + expect(NumberOfLocalMaximumPoints(Array)).toEqual(1) + }) + + it('test boundry maximom points - first element', () => { + const Array = [13, 6, 5, 4, 3, 2, 1] + expect(NumberOfLocalMaximumPoints(Array)).toEqual(1) + }) + + it('test boundry maximom points - both boundries have maximum points', () => { + // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions) + const Array = [13, 2, 3, 4, 5, 6, 12] + expect(NumberOfLocalMaximumPoints(Array)).toEqual(2) + }) + + it('multiple maximom points in the middle', () => { + // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions) + const Array = [1, 3, 2, 5, 6, 9, 2, 7, 12, 1, 0] + expect(NumberOfLocalMaximumPoints(Array)).toEqual(3) + }) + + it('multiple maximom points in the middle with one at end', () => { + // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions) + const Array = [1, 3, 2, 5, 6, 9, 2, 7, 12, 1, 10] + expect(NumberOfLocalMaximumPoints(Array)).toEqual(4) + }) + + it('multiple maximom points in the middle with one at start', () => { + // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions) + const Array = [10, 3, 2, 5, 6, 9, 2, 7, 12, 1, 0] + expect(NumberOfLocalMaximumPoints(Array)).toEqual(3) + }) + + it('multiple maximom points in the middle with two more at both ends', () => { + // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions) + const Array = [10, 3, 11, 5, 6, 9, 2, 7, 12, 1, 10] + expect(NumberOfLocalMaximumPoints(Array)).toEqual(5) + }) +})