회문 문자열 풀이: 양끝 비교로 대소문자 없이 판별하기

·설명 약 8분·작성: 해비·블로그 소개

읽기 전에 알아두면 좋아요

아래 개념이 익숙하면 본문을 바로 읽으세요. 낯선 개념만 링크에서 복습하면 됩니다.

개념과 예제는 실행하지 않아도 읽을 수 있습니다. 내 컴퓨터·터미널에서 직접 실행하는 과정은 선택 실습입니다.

과정 위치와 선택 복습 안내

과정 위치: 문자열 응용 · 문제

과정 위치는 이 글이 속한 묶음입니다. 이 단계의 모든 개념을 먼저 읽을 필요는 없습니다. 위에 연결한 개념 중 낯선 내용만 복습하세요. 문제의 조건·상태·갱신 순서는 익숙한 언어로 설명하면 됩니다.

JavaScript로 문법·실행 복습하기 (선택)

개념 글의 코드는 JavaScript 예시입니다. 문제 화면에서는 JavaScript·Python·Java·C++·C# 중 익숙한 언어의 함수를 작성하세요. 본문의 Node.js 입출력 예시는 로컬 실행을 위한 별도 안내입니다.

회문 문자열 문제는 대소문자를 어떻게 취급하며 판별 결과를 어떤 값으로 나타내나요?

대소문자를 구분하지 않을 때 문자열이 회문인지 YES 또는 NO로 판별하는 문제입니다. 문자열·인덱스·비교의 기본을 준비하고, 아래 입력·반환 계약을 확인해 직접 풀어보세요.

적용 조건·범위: 문자를 삭제하는 조건은 없습니다. 알파벳 이외의 문자를 임의로 걸러내지 않습니다.

본문 근거: MDN toLowerCase 문서

문제·입출력·제약

앞에서 읽은 순서와 뒤에서 읽은 순서가 같은 문자열을 회문 문자열이라고 합니다. 주어진 문자열이 회문이면 YES, 회문이 아니면 NO를 출력합니다. 검사할 때 대소문자는 구분하지 않습니다.

  • 입력: 첫 줄에 공백이 없는 문자열 하나가 주어집니다.
  • 길이: 100을 넘지 않습니다. 원문에는 별도의 최소 길이가 명시되어 있지 않습니다.
  • 출력: YES 또는 NO를 한 줄로 출력합니다.
  • 문자를 삭제하는 조건은 없습니다. 알파벳 이외의 문자를 임의로 걸러내지 않습니다.

제공된 알고리즘 자료의 「섹션 3. 문자열 탐색.pdf」 1쪽과 「1. 회문문자열.txt」를 2026년 10월 6일 직접 확인했습니다. 원본 TXT는 문자열을 함수에 직접 전달하는 예제입니다. 아래에서는 그 비교 방식을 유지하면서 PDF의 첫 줄 입력을 Node.js 표준 입력으로 연결합니다. 원본에 특정 온라인 채점 사이트나 필수 런타임은 제시되어 있지 않습니다.

PDF의 원본 예제 입력

gooG

PDF의 원본 예제 출력

YES

원본 TXT에는 gooG와 goooG를 넣는 실행 예제가 있습니다. goooG의 출력값을 별도로 적어 놓지는 않았으며, 이번에 실제 실행해서 YES를 확인했습니다.

목차

먼저 원본 예제 gooG의 문자 네 개를 종이에 나란히 적어 보세요.

  1. 첫 문자 g와 마지막 문자 G는 이 문제에서 같은 것으로 볼 수 있나요?
  2. 그다음에 비교할 두 문자의 인덱스는 무엇인가요?
  3. 길이가 홀수인 goooG에서 가운데 o를 다른 문자와 비교해야 하나요?

양끝부터 안쪽으로 짝을 지어 보면 필요한 비교 횟수가 보입니다. 서로 다른 한 쌍을 발견했을 때 어떤 결과를 바로 반환할지도 정해 보세요.

직접 풀어보기

먼저 선택한 언어의 입력·반환 계약에 맞춰 작성해 보세요. 힌트 받기와 정답과 비교하기는 코드를 실행하지 않는 AI 분석입니다. 해답·해설은 아래에서 필요할 때 펼칠 수 있습니다.

0 / 6,000바이트

첫 줄 전체를 읽고 대소문자를 구분하지 않는 회문 여부를 문자열 YES 또는 NO로 반환합니다. 입력 문자를 삭제하지 않습니다. 입력 예시 전체를 문자열 input으로 전달하고 출력 문자열을 반환합니다. solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. LF·CRLF·끝 줄바꿈 없음에 같은 결과를 반환합니다. Tab은 다음 항목으로 이동합니다. 입력 영역 오른쪽 아래를 끌어 높이를 조절할 수 있습니다.

비밀키·개인정보는 입력하지 마세요. 코드는 이 페이지에만 유지됩니다.

해답·해설 보기
JavaScript 해답
function solve(input) {
    const text = input.split(/\r?\n/, 1)[0].toLowerCase();
    let left = 0;
    let right = text.length - 1;
    while (left < right) {
        if (text[left] !== text[right]) return 'NO';
        left++;
        right--;
    }
    return 'YES';
}

첫 줄 전체를 읽고 대소문자를 구분하지 않는 회문 여부를 문자열 YES 또는 NO로 반환합니다. 입력 문자를 삭제하지 않습니다. 입력 예시 전체를 문자열 input으로 전달하고 출력 문자열을 반환합니다. solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. LF·CRLF·끝 줄바꿈 없음에 같은 결과를 반환합니다.

접근 과정

1. 비교 기준을 소문자로 통일합니다

g와 G를 그대로 비교하면 다른 문자입니다. 먼저 text.toLowerCase()로 소문자 문자열을 만들어, 문제의 “대소문자를 구분하지 않는다”는 조건을 비교 전에 반영합니다. 변환된 문자열을 normalized에 저장하고 그 길이를 사용합니다.

2. 왼쪽 인덱스에 대응하는 오른쪽 인덱스를 구합니다

길이가 length라면 마지막 인덱스는 length-1입니다. 왼쪽 인덱스 left에 대응하는 오른쪽 인덱스는 length - 1 - left입니다. left가 0, 1, 2로 증가하면 오른쪽은 마지막 위치부터 하나씩 줄어듭니다.

3. 절반만 비교하고, 불일치하면 바로 종료합니다

길이가 4이면 (0,3), (1,2) 두 쌍만 확인하면 됩니다. 길이가 5여도 (0,4), (1,3)만 확인하면 되고, 가운데 문자는 자기 자신과 대응합니다. 따라서 left < Math.floor(length / 2)인 동안 반복합니다. 한 쌍이라도 다르면 NO를 반환하고, 반복문을 모두 통과한 경우에만 YES를 반환합니다.

원본 TXT에는 양끝 비교와 문자열 뒤집기 두 방식이 있습니다. 여기서는 원본의 양끝 비교 방식을 선택했습니다. 인덱스에 역할이 드러나는 이름을 붙이고 엄격한 불일치 비교를 사용했습니다. 한 방법을 끝까지 이해할 수 있도록 전체 코드는 한 번만 제시합니다.

해설과 정답의 근거

회문에서는 왼쪽에서 k번째 문자와 오른쪽에서 k번째 문자가 같아야 합니다. 반복문은 이 대칭 쌍을 바깥에서 안쪽 순서로 빠짐없이 확인합니다.

불일치한 쌍을 발견하면 앞에서 읽은 순서와 뒤에서 읽은 순서가 이미 다르므로, 남은 쌍을 검사하지 않아도 NO입니다. 반대로 모든 대칭 쌍이 같으면 어느 방향으로 읽어도 동일합니다. 홀수 길이의 가운데 문자는 어느 방향에서나 같은 위치에 있으므로 별도 검사가 필요하지 않습니다.

중요한 점은 YES를 반복문 안에서 성급하게 반환하지 않는 것입니다. 바깥 두 문자가 같아도 안쪽에서 다를 수 있으므로, 성공 판정은 모든 쌍을 확인한 뒤에 내립니다.

Node.js 실행 환경에서 아래 코드를 solution.cjs에 저장하세요. 원본 예제 입력을 input.txt에 넣고 node solution.cjs < input.txt를 실행하면 YES가 출력됩니다. 별도 패키지는 필요하지 않습니다. 실행 환경을 먼저 준비해야 한다면 코딩테스트 자료구조 로드맵을 참고하세요.

const fs = require("fs");

const input = fs.readFileSync(0, "utf8").split(/\r?\n/)[0];

function solution(text) {
  const normalized = text.toLowerCase();
  const length = normalized.length;

  for (let left = 0; left < Math.floor(length / 2); left += 1) {
    const right = length - 1 - left;

    if (normalized[left] !== normalized[right]) {
      return "NO";
    }
  }

  return "YES";
}

console.log(solution(input));

/\r?\n/은 LF와 CRLF 줄바꿈을 구분하고 첫 줄의 문자열만 가져옵니다. 입력 끝에 줄바꿈이 없어도 같은 문자열을 읽습니다. 공백을 제거하거나 특수문자를 거르는 전처리는 추가하지 않았습니다.

Node.js 공식 fs.readFileSync 문서에서 파일 디스크립터와 UTF-8 문자열 읽기를 확인했습니다. 소문자 변환이 새 문자열을 반환한다는 점은 MDN toLowerCase 문서를 참고했습니다. 두 문서는 2026년 10월 6일 확인했습니다.

예제 추적

PDF의 gooG를 소문자로 바꾸면 goog이고, 길이는 4입니다. 코드의 인덱스는 0부터 시작합니다.

  1. left=0, right=3: g와 g가 같으므로 다음 쌍으로 이동합니다.
  2. left=1, right=2: o와 o가 같습니다.
  3. left가 2가 되면 반복 조건을 만족하지 않습니다. 두 쌍이 모두 같으므로 YES를 반환합니다.

TXT의 goooG는 gooog로 바뀝니다. (0,4)의 g와 g, (1,3)의 o와 o를 비교하고 가운데 인덱스 2의 o는 건너뜁니다. 실제 실행 결과도 YES입니다.

경계값과 시간·공간 복잡도

아래는 구현을 확인하려고 별도로 만든 경계값입니다. 원본 문제에 수록된 추가 예제가 아닙니다.

  • 한 글자 a: 비교할 쌍이 없어서 YES입니다.
  • 두 글자 aA와 aB: 대소문자만 다르면 YES, 실제 문자가 다르면 NO입니다.
  • abca: 바깥 a 쌍은 같지만 안쪽 b와 c가 달라 NO입니다.
  • 길이 100의 동일 문자 문자열: 50쌍을 확인한 뒤 YES입니다.
  • 길이 100에서 첫 쌍 또는 마지막 비교 쌍만 다르게 만든 입력: 각각 NO입니다.

Node.js v24.19.0에서 본문의 최종 코드를 그대로 실행했습니다. PDF·TXT의 원본 입력 2종과 별도 구성한 13종을 LF·CRLF·끝 줄바꿈 없음으로 각각 실행한 45개 검사가 모두 예상 결과와 일치했습니다. 길이 99·100, 홀수의 가운데, 대소문자 혼합, 바깥·안쪽 불일치, 문자를 임의로 삭제하지 않는 동작을 확인했습니다.

  • 시간 복잡도: 길이 n의 입력 읽기와 소문자 변환이 O(n), 대칭 비교가 최대 ⌊n/2⌋번이므로 전체 O(n)입니다. 첫 쌍에서 불일치해도 소문자 변환은 이미 수행됩니다.
  • 공간 복잡도: 소문자로 변환한 문자열을 보관하므로 O(n)입니다. 인덱스 변수와 비교 반복문 자체의 추가 공간만 보면 O(1)입니다.

원본과 동일하게 JavaScript 문자열 인덱스로 비교합니다. 이 풀이는 이모지나 결합 문자를 화면에 보이는 한 글자 단위로 나누는 범용 Unicode 처리까지 확장하지 않습니다.

자가 확인

  1. 오른쪽 인덱스를 length-left로 쓰면 왜 잘못될까요?
  2. 첫 쌍이 같다는 이유만으로 YES를 반환하면 abca에서 어떤 문제가 생길까요?
  3. 홀수 길이에서 가운데 문자를 생략할 수 있는 이유와, 전체 공간 복잡도가 O(n)인 이유를 설명해 보세요.
확인 기준 보기

마지막 유효 인덱스는 length-1이므로 오른쪽 인덱스는 length-1-left입니다. abca는 안쪽 b와 c가 달라 NO여야 하므로 모든 쌍을 확인해야 합니다. 가운데 문자는 자기 자신과 대응하며, 소문자로 바꾼 새 문자열을 저장하므로 전체 공간은 O(n)입니다.

입력을 소문자로 통일하고, 대칭 인덱스를 구하고, 불일치를 만나면 종료하는 세 과정을 직접 설명할 수 있다면 이번 풀이의 목표를 달성한 것입니다. 반복문 흐름이 헷갈리면 JavaScript 조건문과 반복문을 복습하세요. 제공 자료의 앞 문제는 봉우리이며, 다음 문제는 알파벳만 골라 검사하는 “유효한 팰린드롬”입니다.

글 소개·학습 준비·전체 목차

회문 문자열은 대소문자를 통일한 뒤, 양끝에서 마주 보는 문자가 모두 같은지 확인하면 판별할 수 있습니다. 이 글에서는 “문자열 전체를 뒤집지 않고 회문인지 어떻게 검사할까요?”라는 질문을 해결합니다. 문자열 인덱스, 조건문, 반복문을 알고 있다면 YES 또는 NO를 출력하는 JavaScript 풀이를 직접 완성할 수 있습니다.

양끝에서 같은 문자를 비교하는 회문 문자열을 표현한 파스텔색 LEVEL 타일과 오른쪽 아래 작은 BlogFlow 곰 캐릭터

이 글이 도움이 되었나요?

조회 중

이어서 공부하기

체크포인트: 해설을 가리고 다시 풀고, 경계 입력을 하나 바꾸어 예상 결과와 실제 결과를 비교하세요. 전처리할 문자와 비교할 문자를 구분하고 마지막 문자·마지막 묶음을 확인하세요.

다음 추천 · 문제: 유효한 팰린드롬 풀이: 알파벳만 남겨 회문을 판별하는 방법

같은 주제의 문제에 적용하며 방금 배운 개념을 확인합니다.

권장 순서는 학습 가이드와 같습니다. 다른 순서는 접힌 참고 목록에서 확인할 수 있습니다. 읽음 표시는 숙달이나 채점 결과가 아닙니다.

원래 과정 목록 순서 (선택)

읽음 기록

읽음 — / 전체 57개 · 필수 57개

이 글을 쓴 해비

웹사이트를 제작·운영하고, 개인 서비스와 자동화·AI 도구를 만듭니다. 직접 만들며 배운 내용과 문제 해결 과정을 BlogFlow에 기록합니다.

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기