diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100755 new mode 100644 diff --git a/DIRECTORY.md b/DIRECTORY.md index 7f6484cae5..c1c7916d75 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -73,6 +73,7 @@ * [NumberOfLocalMaximumPoints](Data-Structures/Array/NumberOfLocalMaximumPoints.js) * [QuickSelect](Data-Structures/Array/QuickSelect.js) * [Reverse](Data-Structures/Array/Reverse.js) + * [MooreVotingAlgorithm](Data-Structures/Array/MooreVotingAlgorithm.js) * **Graph** * [Graph](Data-Structures/Graph/Graph.js) * [Graph2](Data-Structures/Graph/Graph2.js) diff --git a/Data-Structures/Array/MooreVotingAlgorithm.js b/Data-Structures/Array/MooreVotingAlgorithm.js new file mode 100644 index 0000000000..17ae0881ba --- /dev/null +++ b/Data-Structures/Array/MooreVotingAlgorithm.js @@ -0,0 +1,29 @@ +/** + * Moore Voting Algorithm to find the majority element in an array + * Majority element is the one that appears more than n/2 times + * geeksforgeeks: https://www.geeksforgeeks.org/boyer-moore-majority-voting-algorithm/ + * @param {Array} arr array of integers + * @returns {Number} majority element or null if no majority exists + */ +const MooreVotingAlgorithm = (arr) => { + let candidate = null + let count = 0 + + // Phase 1: Find the candidate for majority element + for (let num of arr) { + if (count === 0) { + candidate = num + } + count += num === candidate ? 1 : -1 + } + + // Phase 2: Verify if the candidate is actually the majority element + count = 0 + for (let num of arr) { + if (num === candidate) { + count++ + } + } + return count > arr.length / 2 ? candidate : null +} +export { MooreVotingAlgorithm } diff --git a/Data-Structures/Array/test/MooreVotingAlgorithm.test.js b/Data-Structures/Array/test/MooreVotingAlgorithm.test.js new file mode 100644 index 0000000000..1682c25089 --- /dev/null +++ b/Data-Structures/Array/test/MooreVotingAlgorithm.test.js @@ -0,0 +1,11 @@ +import { MooreVotingAlgorithm } from '../MooreVotingAlgorithm' +describe('Moore Voting Algorithm', () => { + it.each([ + [[1, 1, 2, 1, 3, 1, 1], 1], // Majority element 1 + [[2, 2, 2, 2, 5, 5, 5, 2], 2], // Majority element 2 + [[3], 3], // Single element, it's the majority + [[1, 2, 3, 4, 5, 6, 7], null] // No majority element in the array + ])('returns %j when given %j', (array, expected) => { + expect(MooreVotingAlgorithm(array)).toEqual(expected) + }) +}) diff --git a/Maths/MobiusFunction.js b/Maths/MobiusFunction.js index bd268b8bbd..4bc1b33f5c 100644 --- a/Maths/MobiusFunction.js +++ b/Maths/MobiusFunction.js @@ -18,16 +18,19 @@ * @param {Integer} number * @returns {Integer} */ - import { PrimeFactors } from './PrimeFactors.js' + export const mobiusFunction = (number) => { - const primeFactorsArray = PrimeFactors(number) if (number <= 0) { throw new Error('Number must be greater than zero.') } - return primeFactorsArray.length !== new Set(primeFactorsArray).size - ? 0 - : primeFactorsArray.length % 2 === 0 - ? 1 - : -1 + + const primeFactorsArray = PrimeFactors(number) + const uniquePrimeFactors = new Set(primeFactorsArray) + + // If there are duplicate factors, it means number is not square-free. + if (primeFactorsArray.length !== uniquePrimeFactors.size) { + return 0 + } + return uniquePrimeFactors.size % 2 === 0 ? 1 : -1 } diff --git a/package-lock.json b/package-lock.json index 5c38ba06a8..58e15a8c63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@vitest/coverage-v8": "^1.2.1", "globby": "^13.2.2", "husky": "^8.0.3", - "prettier": "^3.0.3", + "prettier": "^3.3.3", "vitest": "^1.2.1" }, "engines": { @@ -1662,7 +1662,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index e667e1eea2..122e9952bf 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,11 @@ "author": "TheAlgorithms", "license": "GPL-3.0", "devDependencies": { + "@vitest/coverage-v8": "^1.2.1", "globby": "^13.2.2", "husky": "^8.0.3", - "prettier": "^3.0.3", - "vitest": "^1.2.1", - "@vitest/coverage-v8": "^1.2.1" + "prettier": "^3.3.3", + "vitest": "^1.2.1" }, "engines": { "node": ">=20.6.0"