Не надо сравнивать каждый с каждым, считайте количество повторений:
function duplicateEncode(str) {
const arr = [...str.toLowerCase()];
const count = arr.reduce((acc, n) => (acc[n] = (acc[n] || 0) + 1, acc), {});
return arr.map(n => count[n] > 1 ? ')' : '(').join('');
}
Или не считайте:
function duplicateEncode(str) {
const arr = str.toLowerCase().split('');
const duplicates = arr.reduce((acc, n) => (acc[n] = acc.hasOwnProperty(n), acc), {});
return ''.concat(...arr.map(n => '()'[+duplicates[n]]));
}
const duplicateEncode = str => Object
.values(Object
.values(str.toLowerCase())
.reduce((acc, n, i) => ((acc[n] = acc[n] || []).push(i), acc), {}))
.reduce((acc, n) => (n.forEach(i => acc[i] = n.length > 1 ? ')' : '('), acc), [])
.join``;
const duplicateEncode = str => Array
.from(str.toLowerCase())
.reduce((acc, n, i, a) => acc + (a.indexOf(n) === a.lastIndexOf(n) ? '(' : ')'), '');
const duplicateEncode = str => str
.toLowerCase()
.replace(/./g, (m, _, s) => String.fromCharCode(40 + (s.split(m).length > 2)));