문제 이해하기
문자열을 하나 입력받아, 해당 문자열의 모든 문자가 각각 한 번씩만 등장하면 true를, 중복된 문자가 존재하면 false를 반환하는 JavaScript 함수를 작성하는 것이 목표입니다.
예를 들어 'thisconaluqe'처럼 어떤 문자도 반복되지 않는 문자열이라면 결과는 true여야 하고, 'hello'처럼 같은 문자가 두 번 이상 나타나는 문자열이라면 결과는 false가 되어야 합니다.
해결 접근 방식
이 문제는 indexOf()와 lastIndexOf() 메서드를 활용하면 간단하게 해결할 수 있습니다.
indexOf(el): 특정 문자가 문자열에서 처음으로 등장하는 위치(인덱스)를 반환합니다.lastIndexOf(el): 특정 문자가 문자열에서 마지막으로 등장하는 위치(인덱스)를 반환합니다.
문자열의 각 문자에 대해 이 두 값이 서로 다르다면, 그 문자가 최소 두 번 이상 등장했다는 의미이므로 즉시 false를 반환하면 됩니다. 반복문이 끝날 때까지 중복이 발견되지 않았다면 모든 문자가 고유하다는 뜻이므로 true를 반환합니다.
예제 코드
다음은 전체 구현 코드입니다 −
const str = 'thisconaluqe';
const allUnique = (str = '') => {
for(let i = 0; i < str.length; i++){
const el = str[i];
if(str.indexOf(el) !== str.lastIndexOf(el)){
return false;
};
};
return true;
};
console.log(allUnique(str));
출력 결과
true
코드 설명
allUnique 함수는 화살표 함수로 정의되었으며, 빈 문자열이 전달될 경우를 대비해 기본 매개변수 값으로 ''를 설정했습니다.
반복문을 통해 문자열의 첫 번째 문자부터 마지막 문자까지 순서대로 확인합니다. 현재 문자 el의 첫 등장 위치와 마지막 등장 위치가 일치하지 않으면(indexOf !== lastIndexOf) 해당 문자가 중복된 것이므로 곧바로 false를 반환하고 함수 실행을 종료합니다.
모든 문자를 검사했음에도 중복이 발견되지 않았다면, 문자열의 모든 문자가 고유하다는 것이 확인된 것이므로 최종적으로 true를 반환합니다. 위 예제에서 사용한 'thisconaluqe'에는 반복되는 문자가 없기 때문에 콘솔에는 true가 출력됩니다.
참고: 시간 복잡도
이 방식은 각 문자마다 indexOf와 lastIndexOf를 호출하므로 시간 복잡도는 O(n²)입니다. 문자열이 매우 길다면 Set 객체를 활용해 O(n)으로 개선할 수 있습니다.
const allUniqueOptimized = (str = '') => {
return new Set(str).size === str.length;
};
console.log(allUniqueOptimized('thisconaluqe')); // true
Set은 중복 값을 허용하지 않으므로, 문자열을 Set으로 변환했을 때의 크기가 원래 문자열의 길이와 같다면 모든 문자가 고유하다는 것을 의미합니다.