You can improve the function's time complexity at the expense of memory by tracking the duplicates in a separate [Set][1]. This will reduce the number of iterations by the number of unique items in the input array, and increase the memory need by the same number. A further improvement can be gained if you delete duplicates from the unique set as you go. This will bring the memory use down. <!-- begin snippet: js hide: false console: true babel: false --> <!-- language: lang-js --> function countDuplicates(original) { const uniqueItems = new Set(); const duplicates = new Set(); for (const value of original) { if (uniqueItems.has(value)) { duplicates.add(value); uniqueItems.delete(value); } else { uniqueItems.add(value); } } return duplicates.size; } /* Test code not related to solution */ function test(name, func, data, result) { const output = `${name} [${data.join(", ")}] : `; console.log(output + (func(data) === result ? "passed" : "failed")); } test("1 duplicate ", countDuplicates, [9, 11, 12, 2, 7, 4, 2], 1); test("1 duplicate ", countDuplicates, [6, 6, 6], 1); test("2 duplicates ", countDuplicates, [0, 1, 4, 2, 7, 4, 2], 2); test("3 duplicates ", countDuplicates, [0, 1, 4, 2, 7, 4, 2, 0], 3); test("No duplicates ", countDuplicates, [0, 1, 4, 2, 7, 5, 8, 9], 0); <!-- end snippet --> [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set