읽기 전에 알아두면 좋아요
아래 개념이 익숙하면 본문을 바로 읽으세요. 낯선 개념만 링크에서 복습하면 됩니다.
- 문자열 알고리즘 기초: 순회·문자 판별·대소문자 변환·숫자 추출문자열의 각 문자를 순서대로 읽고 위치를 확인하는 방법을 복습합니다. 현재 풀이: indexOf/find로 최초 등장 위치를 확인해 중복을 제거하고 순서를 보존합니다.
개념과 예제는 실행하지 않아도 읽을 수 있습니다. 내 컴퓨터·터미널에서 직접 실행하는 과정은 선택 실습입니다.
과정 위치와 선택 복습 안내
과정 위치: 문자열 기초 · 문제
과정 위치는 이 글이 속한 묶음입니다. 이 단계의 모든 개념을 먼저 읽을 필요는 없습니다. 위에 연결한 개념 중 낯선 내용만 복습하세요. 문제의 조건·상태·갱신 순서는 익숙한 언어로 설명하면 됩니다.
다른 풀이와 비용 비교 (선택)
- JavaScript Map·Set: 값 조회와 중복 제거 실습Map은 이름표인 키로 값을 찾고, Set은 같은 값을 한 번만 보관합니다. 다른 풀이: Set으로 중복을 관리하는 방법과 반복 검색의 비용을 비교합니다.
JavaScript로 문법·실행 복습하기 (선택)
개념 글의 코드는 JavaScript 예시입니다. 문제 화면에서는 JavaScript·Python·Java·C++·C# 중 익숙한 언어의 함수를 작성하세요. 본문의 Node.js 입출력 예시는 로컬 실행을 위한 별도 안내입니다.
중복문자제거 문제의 결과에서는 어떤 순서를 유지해야 하나요?
문자열에서 중복 문자를 제거하고 최초 등장 순서를 유지한 결과를 반환하는 문제입니다. 문자열·인덱스·중복의 기본을 준비하고, 아래 입력·반환 계약을 확인해 직접 풀어보세요.
적용 조건·범위: 이번 대조는 원자료의 문제 조건과 예제 확인입니다. 이 글의 전체 코드를 새로 실행하거나 공식 채점에 제출한 결과를 뜻하지 않습니다. 아래 예제·자가 확인 항목은 직접 실행해 기대 출력과 비교하는 기준입니다.
공식 문서 참고: 관련 개념: MDN 문자열 indexOf의 최초 위치
문제
소문자로 이루어진 문자열 하나가 주어집니다. 같은 문자가 여러 번 나타나면 첫 번째 문자만 남기고 나머지는 제거해야 하며, 남은 문자의 순서는 원래 문자열에서 처음 등장한 순서를 유지해야 합니다.
| 구분 | 내용 |
|---|---|
| 입력 | 첫 줄에 소문자 문자열 하나 |
| 출력 | 중복 문자를 제거한 문자열 |
| 예제 | ksekkset → kset |
예제에서는 첫 번째 k, s, e가 차례로 남습니다. 뒤에서 다시 만나는 k, s, e는 이미 등장했으므로 건너뛰고, 마지막에 처음 등장하는 t를 추가하면 kset이 됩니다.
직접 풀어보기
먼저 선택한 언어의 입력·반환 계약에 맞춰 작성해 보세요. 힌트 받기와 정답과 비교하기는 코드를 실행하지 않는 AI 분석입니다. 해답·해설은 아래에서 필요할 때 펼칠 수 있습니다.
AI 힌트
코드를 실행한 채점 결과가 아닌 AI의 코드 분석입니다.
해답·해설 보기
function solution(text) {
let result = '';
for (let i = 0; i < text.length; i++) if (text.indexOf(text[i]) === i) result += text[i];
return result;
}
solution(text)에 문자열을 전달하며 결과 문자열을 반환합니다. 입력은 문제의 유효한 범위를 만족합니다. 표준 입력·출력 없이 결과를 반환하세요.
def solution(text):
result = []
for i, ch in enumerate(text):
if text.find(ch) == i: result.append(ch)
return ''.join(result)
solution(text)에 문자열을 전달하며 결과 문자열을 반환합니다. 입력은 문제의 유효한 범위를 만족합니다. 표준 입력·출력 없이 결과를 반환하세요.
import java.util.*;
class Solution {
public String solution(String text) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < text.length(); i++) if (text.indexOf(text.charAt(i)) == i) result.append(text.charAt(i));
return result.toString();
}
}
Solution.solution(String text)에 문자열을 전달하며 결과 문자열을 반환합니다. 입력은 문제의 유효한 범위를 만족합니다. 표준 입력·출력 없이 결과를 반환하세요.
#include <algorithm>
#include <array>
#include <functional>
#include <list>
#include <limits>
#include <memory>
#include <numeric>
#include <queue>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;
string solution(const string & text) {
string result;
for (size_t i = 0; i < text.size(); i++) if (text.find(text[i]) == i) result += text[i];
return result;
}
solution(text)에 문자열을 전달하며 결과 문자열을 반환합니다. 입력은 문제의 유효한 범위를 만족합니다. 표준 입력·출력 없이 결과를 반환하세요.
using System;
using System.Collections.Generic;
using System.Text;
public class Solution {
public string Solve(string text) {
var result = new StringBuilder();
for (int i = 0; i < text.Length; i++) if (text.IndexOf(text[i]) == i) result.Append(text[i]);
return result.ToString();
}
}
Solution.Solve(string text)에 문자열을 전달하며 결과 문자열을 반환합니다. 입력은 문제의 유효한 범위를 만족합니다. 표준 입력·출력 없이 결과를 반환하세요.
원자료와 확인 범위
2026-10-12에 제공된 학습 자료 섹션 1. 기본문제풀이.pdf의 16쪽 ‘중복문자제거’와 문제 조건·예제를 대조했습니다. 같은 ZIP의 해당 문제 TXT는 풀이 코드 자료입니다. 이 자료의 최초 출제 원문·저자·공개 배포 주소까지 확인한 것은 아닙니다.
이번 대조는 원자료의 문제 조건과 예제 확인입니다. 이 글의 전체 코드를 새로 실행하거나 공식 채점에 제출한 결과를 뜻하지 않습니다. 아래 예제·자가 확인 항목은 직접 실행해 기대 출력과 비교하는 기준입니다.
제공된 풀이의 주요 조건은 현재 인덱스와 해당 문자가 처음 나타난 인덱스를 비교하는 것입니다. 두 값이 같을 때만 결과 문자열에 문자를 붙이면 중복을 제거하면서 최초 등장 순서를 보존할 수 있습니다.
알고리즘 설계

indexOf는 문자열에서 지정한 문자가 처음 나타나는 위치를 반환합니다. 반복문의 현재 위치가 input.indexOf(input[index])와 같다면 지금 보고 있는 문자는 처음 등장한 문자입니다. 반대로 두 값이 다르면 같은 문자가 앞에 이미 있으므로 결과에 추가하지 않습니다.
이 판단을 문자열의 처음부터 끝까지 적용하면 각 문자는 처음 등장했을 때 정확히 한 번만 선택됩니다. 결과에 문자를 붙이는 순서도 입력을 순회하는 순서와 같기 때문에 별도의 정렬 없이 원래 순서가 유지됩니다.
| 현재 위치 | 문자 | 최초 위치 | 처리 |
|---|---|---|---|
| 0 | k |
0 | 추가 |
| 1 | s |
1 | 추가 |
| 2 | e |
2 | 추가 |
| 3 | k |
0 | 건너뜀 |
| 7 | t |
7 | 추가 |
문자열 인덱스와 반복문을 준비한 뒤 아래 전체 코드를 solution.cjs로 저장합니다. Node.js에서 표준 입력을 읽는 코드이므로 브라우저 Console에 그대로 붙여 넣지 않습니다. input.txt 한 줄에 ksekkset을 넣고 PowerShell 7의 Get-Content -Raw -Encoding UTF8 ./input.txt | node ./solution.cjs 또는 Bash·명령 프롬프트의 node solution.cjs < input.txt로 실행하세요. 기대 출력 kset과 비교하고 t가 처음 나오는 마지막 위치도 선택되는지 확인합니다. 이번 본문 보완에서는 코드를 실행하지 않았습니다.

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 풀이에서도 이어서 확인할 수 있습니다.
이 문제를 푼 뒤 확인하기
문자가 처음·중간·끝에서 반복되는 경우 원래 등장 순서가 유지되는지 확인해 보세요.
본문의 예제와 이 반례를 직접 실행해 예상 출력과 비교하고, 결과가 다르면 입력 조건과 반복 범위를 다시 확인하세요.
글 소개·학습 준비·전체 목차
현재 인덱스가 그 문자의 최초 등장 인덱스와 같을 때만 남기면 중복을 제거하면서 원래 순서를 유지할 수 있습니다. 문자열을 왼쪽부터 확인하며 indexOf의 위치와 비교해 보세요. 해설과 정답은 아래 접힌 영역에서 확인할 수 있습니다.
이 글이 도움이 되었나요?
이어서 공부하기
체크포인트: 해설을 가리고 다시 풀고, 경계 입력을 하나 바꾸어 예상 결과와 실제 결과를 비교하세요. 같은 문자·찾는 문자 없음·홀짝 길이를 확인하고 결과의 등장 순서를 설명하세요.
다음 추천 · 문제: 중복단어제거 풀이
권장 순서는 학습 가이드와 같습니다. 다른 순서는 접힌 참고 목록에서 확인할 수 있습니다. 읽음 표시는 숙달이나 채점 결과가 아닙니다.
원래 과정 목록 순서 (선택)
읽음 기록
읽음 — / 전체 58개 · 필수 58개
새 글 받아보기
RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.