문제 소개
백준 18870번 "좌표 압축"은 정렬과 해시맵을 활용하는 대표적인 문제입니다.
문제 요약
- 수직선 위의 N개 좌표를 압축하는 문제
- 각 좌표를 "자신보다 작은 서로 다른 좌표의 개수"로 변환
- 예: [2, 4, -10, 4, -9] → [2, 3, 0, 3, 1]
핵심 개념: 좌표 압축이란?
좌표 압축 = 순위 매기기!
좌표 압축은 큰 범위의 좌표들을 작은 범위로 압축하는 기법입니다.
원본 좌표: -10억 ~ 10억 범위
압축 후: 0 ~ N-1 범위
실생활 비유
학교에서 시험 점수로 등수를 매기는 것과 같습니다!
- 45점 → 3등 (0부터 시작하면 2)
- 97점 → 1등 (0부터 시작하면 0)
- 73점 → 2등 (0부터 시작하면 1)
🔍 문제 접근 방법
Step by Step 풀이 과정
1️⃣ 중복 제거 & 정렬
javascript
// 원본: [2, 4, -10, 4, -9]
// Set으로 중복 제거: [2, 4, -10, -9]
// 정렬: [-10, -9, 2, 4]
2️⃣ 압축값 매핑
javascript
// 작은 수부터 0, 1, 2, 3... 부여
-10 → 0
-9 → 1
2 → 2
4 → 3
3️⃣ 원본 배열 변환
javascript
// 각 원본값을 압축값으로 변환
[2, 4, -10, 4, -9]
[2→2, 4→3, -10→0, 4→3, -9→1]
[2, 3, 0, 3, 1] ✅
💻 전체 코드 구현
방법 1: Map과 forEach 활용
javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin").toString().trim().split("\n");
const N = parseInt(input[0]);
const coords = input[1].split(" ").map(Number);
// 1단계: 중복 제거하고 정렬
const uniqueSorted = [...new Set(coords)].sort((a, b) => a - b);
// 2단계: Map으로 압축값 저장
const compressMap = new Map();
uniqueSorted.forEach((value, index) => {
compressMap.set(value, index);
});
// 3단계: 원본 배열 변환
const result = coords.map(coord => compressMap.get(coord));
console.log(result.join(" "));
방법 2: 객체와 for문 활용
javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin").toString().trim().split("\n");
const N = parseInt(input[0]);
const coords = input[1].split(" ").map(Number);
// 1단계: 중복 제거하고 정렬
const uniqueSorted = [...new Set(coords)].sort((a, b) => a - b);
// 2단계: 객체로 압축값 저장
const compressMap = {};
for (let i = 0; i < uniqueSorted.length; i++) {
compressMap[uniqueSorted[i]] = i;
}
// 3단계: 원본 배열 변환
const result = [];
for (let i = 0; i < N; i++) {
result.push(compressMap[coords[i]]);
}
console.log(result.join(" "));
시각적 이해
예제 1 동작 과정
원본 배열: [2, 4, -10, 4, -9]
↓ 중복 제거 & 정렬
정렬된 배열: [-10, -9, 2, 4]
↓ 인덱스 부여
압축 매핑: {-10:0, -9:1, 2:2, 4:3}
↓ 원본에 적용
결과: [2, 3, 0, 3, 1]
예제 2 동작 과정
원본 배열: [1000, 999, 1000, 999, 1000, 999]
↓ 중복 제거 & 정렬
정렬된 배열: [999, 1000]
↓ 인덱스 부여
압축 매핑: {999:0, 1000:1}
↓ 원본에 적용
결과: [1, 0, 1, 0, 1, 0]
시간복잡도 분석
단계 | 연산 | 시간 복잡도 |
중복 제거 | Set 생성 | O(N) |
정렬 | sort() | O(N log N) |
매핑 생성 | forEach/for | O(N) |
변환 | map/for | O(N) |
전체 | O(N log N) |
⚠️ 주의사항 & 팁
1. 정렬 시 비교 함수 필수!
javascript
// ❌ 잘못된 방법 (문자열 정렬)
arr.sort() // ['-10', '-9', '2', '4']
// ✅ 올바른 방법 (숫자 정렬)
arr.sort((a, b) => a - b) // [-10, -9, 2, 4]
2. Map vs 객체 선택
javascript
// Map 사용 - 더 명확한 의도
const map = new Map();
map.set(key, value);
map.get(key);
// 객체 사용 - 더 간단한 문법
const obj = {};
obj[key] = value;
obj[key];
3. 중복 제거는 Set이 최고!
javascript
// Set으로 간단하게
const unique = [...new Set(array)];
// filter로 하면 복잡 (비추천)
const unique = array.filter((v, i) => array.indexOf(v) === i);
정리
좌표 압축은 정렬 + 해시맵의 조합으로 해결하는 전형적인 패턴입니다.
핵심 요약:
- Set으로 중복 제거
- 정렬로 순서 정하기
- Map/객체로 빠른 검색
- 원본 배열 변환
**시간복잡도 O(N log N)**으로 백만 개의 데이터도 효율적으로 처리할 수 있습니다.
'알고리즘 풀이' 카테고리의 다른 글
백준 | 2805번 나무 자르기 (JavaScript 풀이) (0) | 2025.10.04 |
---|---|
백준 | Class3 핵심 알고리즘 개념 정리 (2) | 2025.09.20 |
백준 | 2606번 바이러스 (JavaScript 풀이) (0) | 2025.09.09 |
백준 | 1463번 1로 만들기 (JavaScript 풀이) (0) | 2025.09.06 |
백준 | 1003번 피보나치 함수 (JavaScript 풀이) (0) | 2025.09.05 |