문자열을 왼쪽부터 확인하면서 각 문자의 첫 등장만 결과에 남기는 조건을 생각해 보세요. 해설과 정답은 아래 접힌 영역에서 확인할 수 있습니다.
문제
소문자로 이루어진 문자열 하나가 주어집니다. 같은 문자가 여러 번 나타나면 첫 번째 문자만 남기고 나머지는 제거해야 하며, 남은 문자의 순서는 원래 문자열에서 처음 등장한 순서를 유지해야 합니다.
| 구분 | 내용 |
|---|---|
| 입력 | 첫 줄에 소문자 문자열 하나 |
| 출력 | 중복 문자를 제거한 문자열 |
| 예제 | ksekkset → kset |
예제에서는 첫 번째 k, s, e가 차례로 남습니다. 뒤에서 다시 만나는 k, s, e는 이미 등장했으므로 건너뛰고, 마지막에 처음 등장하는 t를 추가하면 kset이 됩니다.
풀이와 정답
풀이와 정답 보기 (클릭)
제공된 풀이의 주요 조건은 현재 인덱스와 해당 문자가 처음 나타난 인덱스를 비교하는 것입니다. 두 값이 같을 때만 결과 문자열에 문자를 붙이면 중복을 제거하면서 최초 등장 순서를 보존할 수 있습니다.
알고리즘 설계

indexOf는 문자열에서 지정한 문자가 처음 나타나는 위치를 반환합니다. 반복문의 현재 위치가 input.indexOf(input[index])와 같다면 지금 보고 있는 문자는 처음 등장한 문자입니다. 반대로 두 값이 다르면 같은 문자가 앞에 이미 있으므로 결과에 추가하지 않습니다.
이 판단을 문자열의 처음부터 끝까지 적용하면 각 문자는 처음 등장했을 때 정확히 한 번만 선택됩니다. 결과에 문자를 붙이는 순서도 입력을 순회하는 순서와 같기 때문에 별도의 정렬 없이 원래 순서가 유지됩니다.
| 현재 위치 | 문자 | 최초 위치 | 처리 |
|---|---|---|---|
| 0 | k |
0 | 추가 |
| 1 | s |
1 | 추가 |
| 2 | e |
2 | 추가 |
| 3 | k |
0 | 건너뜀 |
| 7 | t |
7 | 추가 |
JavaScript 풀이

Node.js 표준 입력에서 문자열을 읽고 마지막 줄바꿈만 제거합니다. replace(/r?n$/, "")는 LF와 CRLF 입력의 마지막 개행을 처리하며, 문자열 앞뒤의 실제 문자를 함께 제거하지 않습니다. 그다음 제공 코드의 indexOf 비교 로직을 그대로 적용합니다.
const fs = require("fs");
const input = fs.readFileSync(0, "utf8").replace(/r?n$/, "");
let answer = "";
for (let index = 0; index < input.length; index += 1) {
if (input.indexOf(input[index]) === index) {
answer += input[index];
}
}
console.log(answer);
문자열 전체에 trim()을 적용하면 앞뒤 공백까지 제거됩니다. 이 문제의 입력은 소문자 문자열이므로 결과에는 영향이 없지만, 입력 처리의 의미를 분명하게 하기 위해 마지막 개행만 제거했습니다.
복잡도와 검증
문자열 길이를 N이라고 하면 반복문은 N번 실행됩니다. 각 반복에서 indexOf가 앞에서부터 문자를 찾으므로 최악의 경우 O(N)이 걸려 전체 시간 복잡도는 O(N²)입니다. 입력 문자열과 결과 문자열을 저장하는 데 O(N) 공간이 필요하며, 그 밖의 추가 변수는 O(1)입니다.
| 검증 | 입력 | 출력 |
|---|---|---|
| 원문 예제 | ksekkset |
kset |
| 모두 다름 | abc |
abc |
| 모두 같음 | aaaa |
a |
| 한 글자 | a |
a |
| 교차 중복 | abacb |
abc |
저장 전 코드에서 원문 예제와 경계값을 실행했으며 LF와 CRLF 입력 모두 같은 결과를 확인했습니다. 문자열 순회의 기본은 문자 찾기 JavaScript 풀이, 대소문자 처리 방식은 대문자로 통일 JavaScript 풀이에서도 이어서 확인할 수 있습니다.
풀이 전에 확인할 순서
- 입력값과 출력값을 한 문장으로 다시 적습니다.
- 반복할 대상과 비교·저장할 값을 정합니다.
- 필요한 자료구조와 시간복잡도를 예상합니다.
- 코드를 보기 전에 손으로 작은 예제를 계산합니다.
힌트: 중복문자제거 JavaScript 풀이
정답 코드를 바로 따라 쓰기보다, 본문에서 값이 갱신되는 조건과 반복 범위를 먼저 찾으세요. 반복 한 번마다 반드시 유지되어야 하는 값이 무엇인지 적으면 풀이의 중심 변수를 고르기 쉽습니다.
테스트 확인
- 가능한 가장 작은 입력
- 같은 값이나 문자가 반복되는 입력
- 정답이 처음 또는 마지막 위치에서 결정되는 입력
- 입력 제한에 가까운 경우의 실행 시간
확인 결과: 본문의 예제뿐 아니라 위 경계 사례에서도 예상값과 실제 출력이 같아야 풀이가 완료됩니다.
이 글이 도움이 되었나요?
코딩테스트 JavaScript 학습 순서
필수 49개 · 전체 49개
읽음 기록 관리
전체 과정 목차 (49개)
- 필수 길잡이 · 코딩테스트 JS 자료구조 로드맵: 배열, 해시, 스택, 투 포인터 순서
- 필수 학습 · 세 수 중 최솟값 JavaScript 조건문 풀이 정리
- 필수 학습 · 삼각형 판별하기 JavaScript 풀이
- 필수 학습 · 연필 개수 JavaScript 풀이
- 필수 학습 · 1부터 N까지 합 출력하기 JavaScript 풀이
- 필수 학습 · 최솟값 구하기 JavaScript 풀이|배열 순회와 비교 갱신 원리
- 필수 학습 · 홀수 JavaScript 풀이: 조건 판별과 결과 처리 정리
- 필수 학습 · 10부제 JavaScript 풀이: 끝자리 비교로 위반 차량 수 세기
- 필수 학습 · A를 #으로 JavaScript 풀이: 문자열 순회와 치환
- 필수 학습 · 문자 찾기 JavaScript 풀이: 문자열 순회로 개수 세기
- 필수 학습 · 대문자 찾기 JavaScript 풀이
- 필수 학습 · 대문자로 통일 JavaScript 풀이
- 필수 학습 · 대소문자 변환 JavaScript 풀이
- 필수 학습 · 일곱 난쟁이 JavaScript 풀이: 두 명을 제외하는 완전탐색
- 필수 학습 · 코딩테스트 JS Map 풀이: 학급 회장 득표수 세기
- 필수 학습 · 코딩테스트 JS 스택 풀이: 올바른 괄호 검증하기
- 필수 학습 · 코딩테스트 JS 스택 풀이: 괄호문자 제거하기
- 필수 학습 · 코딩테스트 JS 스택 풀이: 크레인 인형뽑기 처리법
- 필수 학습 · 코딩테스트 JS 스택 풀이: 후위식 연산 계산하기
- 필수 학습 · 코딩테스트 JS 스택 풀이: 쇠막대기 레이저 절단 개수 세기
- 필수 학습 · 코딩테스트 JS 투 포인터 풀이: 두 정렬 배열 합치기
- 필수 학습 · 코딩테스트 JS 투 포인터 풀이: 공통 원소 추출하기
- 필수 학습 · 코딩테스트 JS 슬라이딩 윈도우 풀이: 최대 매출 구간 합 계산하기
- 필수 학습 · JavaScript 투 포인터: 합이 M인 연속 부분수열 개수
- 필수 학습 · 코딩테스트 JS 해시 풀이: 모든 아나그램 찾기
- 필수 학습 · 가장 긴 문자열 JavaScript 풀이
- 필수 학습 · 가운데 문자 출력 JavaScript 풀이
- 필수 학습 · 중복문자제거 JavaScript 풀이 현재 글
- 필수 학습 · 코딩테스트 JS 고급: 최소 힙으로 다익스트라 최단 경로 구하기
- 필수 학습 · 코딩테스트 JS Union-Find: 연결 성분 수와 크기 구하기
- 필수 학습 · 코딩테스트 JS Trie: 접두사에 맞는 단어 수 세기
- 필수 학습 · 코딩테스트 JS Fenwick Tree: 값 갱신과 구간 합 처리
- 필수 학습 · 코딩테스트 JS 세그먼트 트리: 단일 대입과 구간 합
- 필수 학습 · 코딩테스트 JS LRU 캐시: 지도 타일 재사용 기록
- 필수 학습 · 코딩테스트 JS AVL 트리: 기준 이상 최솟값 찾기
- 필수 학습 · 코딩테스트 JS 큐: 상담 창구 대기열 명령 처리
- 필수 학습 · 코딩테스트 JS 연결 리스트: 재생 대기 목록 관리
- 필수 학습 · JavaScript 원형 덱 연습: 최근 기록 창과 되돌리기
- 필수 학습 · JavaScript 해시 테이블 연습: 정규화 문자열 빈도와 등장 순서
- 필수 학습 · JavaScript 트리 순회 연습: 깊이별 노드 묶기
- 필수 학습 · JavaScript BST 연습: 닫힌 구간의 중복 키 보고서
- 필수 학습 · JavaScript 최소 힙 연습: 동률 순서를 지키는 작업 스케줄러
- 필수 학습 · JavaScript 그래프 연습: 연결 구역 크기를 작은 순서로 출력하기
- 필수 학습 · 중복단어제거 JavaScript 풀이
- 필수 학습 · TypeScript 이진 탐색 연습: 숫자 카드 존재 여부 확인
- 필수 학습 · 큰 수 출력하기 JavaScript 풀이
- 필수 학습 · 보이는 학생 JavaScript 풀이
- 필수 학습 · 가위바위보 JavaScript 풀이
- 필수 학습 · 점수계산 JavaScript 풀이
새 글 받아보기
RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.