핵심 아이디어 해시맵(Map) 셋(Set) 코테 3대 활용 충돌 📝 문제풀이
◀ 이전 📋 목차 CH 06 ▶
🗂️ CHAPTER 05 · 자료구조

키를 열쇠 삼아, 값을 바로 꺼낸다

배열을 처음부터 훑으면 O(n)이지만, 해시는 키로 위치를 바로 계산평균 O(1)에 찾아가요. 코테에서 "느린 탐색"을 "즉시 조회"로 바꿔주는 강력한 무기, Map과 Set을 익혀요.

🎯 이 장을 끝내면
🔑
핵심 아이디어
해시는 "키를 위치로 바꿔" 바로 찾아가요
훑지 않고, 계산해서 곧장 가는 게 핵심이에요.

배열에서 어떤 값을 찾으려면 보통 처음부터 하나씩 비교해야 해요 → O(n). 해시는 다르게 접근해요. 키(key)해시 함수에 넣어 저장 위치(버킷)를 계산하고, 그 위치로 곧장 가요. 그래서 평균적으로 조회·삽입·삭제가 O(1)이에요.

🔤
해시(Hash) — 어떤 데이터를 정해진 규칙(계산식)에 넣어 고정된 숫자 하나로 바꾸는 것이에요. 그 숫자를 "어디에 저장할지"를 정하는 위치로 그대로 쓰기 때문에, 데이터를 하나하나 훑지 않고도 계산 한 번으로 바로 그 자리에 갈 수 있어요.
🔤
해시 함수(hash function) — 키를 넣으면 저장할 위치 번호를 뱉어주는 계산 규칙이에요. "이름 → 사물함 번호"로 바꿔주는 변환기라고 보면 돼요. 같은 키를 넣으면 항상 같은 번호가 나와야, 저장한 자리에서 다시 꺼낼 수 있어요.
🔤
버킷(bucket) — 해시가 값을 실제로 담아두는 한 칸 한 칸이에요. 해시 함수가 알려준 번호의 버킷에 값을 넣고, 꺼낼 때도 그 번호의 버킷으로 곧장 가요. 사물함 비유에서 번호가 붙은 사물함 한 칸이 버킷이에요.
🗄️ 비유 — 값을 열쇠로 사물함을 바로 열기 복도 사물함에서 내 물건을 찾는다고 해봐요. 문을 하나씩 다 열어보면 O(n)이에요. 하지만 "이름 → 사물함 번호"로 바꿔주는 규칙(해시 함수)이 있다면, 이름만 넣으면 몇 번 칸인지 바로 나와요. 그 칸으로 곧장 가서 열면 끝 → O(1). 💡 여기서 이름 = 키(key), 사물함 번호 = 위치(버킷), 이름을 번호로 바꾸는 규칙 = 해시 함수예요.
해시 Map Set O(1) 빈도 세기 중복 제거 존재 확인 코딩테스트
🧭
이 장의 예시. 코드는 JavaScriptMap·Set으로 보여드려요. 자바로 치면 각각 HashMap·HashSet에 대응해요. 논리는 언어가 달라도 똑같이 통해요.
🖼️ 그림으로 보기 — 키 → 해시 함수 → 버킷
키(key) 버킷(배열) "김철수" "이영희" "박민수" 🔢 해시 함수 h(key) → 위치 [0]"이영희" [1](빈 칸) [2]"김철수" [3](빈 칸) [4]"박민수"
키를 해시 함수에 넣으면 저장 위치(버킷 번호)가 나와요. 그래서 하나씩 뒤지지 않고 계산한 위치로 곧장 가요 → 평균 O(1). (서로 다른 키가 같은 칸으로 가면 충돌 — 그 칸 안에서만 살짝 더 찾아요.)
🗺️
해시맵(Map)
키 → 값 쌍을 저장해요
JavaScript의 Map = 자바의 HashMap.

해시맵(Map)키(key)와 값(value)을 짝지어 저장하는 자료구조예요. 키로 값을 바로 꺼낼 수 있어요. 대표 메서드는 set(key, val) · get(key) · has(key)예요.

🗺️ Map 기본 사용법
const scores = new Map();

scores.set("철수", 90);   // 키 "철수" → 값 90 저장
scores.set("영희", 85);   // 키 "영희" → 값 85 저장

scores.get("철수");       // 90  (키로 값을 바로 꺼냄)
scores.has("영희");       // true (키가 있나?)
scores.has("민수");       // false
scores.size;              // 2   (저장된 쌍의 개수)
get·set·has 모두 평균 O(1)이에요. 키만 알면 값이 어디 있든 한 번에 접근해요. 💡 없는 키를 get하면 undefined가 나와요. 그래서 값을 꺼내기 전에 has로 확인하거나, 기본값을 함께 처리하는 패턴을 자주 써요.
🎯
셋(Set)
중복 없는 값들의 모음이에요
JavaScript의 Set = 자바의 HashSet.

셋(Set)중복을 허용하지 않는 값들의 모음이에요. 값 자체를 키처럼 쓰는 셈이라, "이 값이 있나?"를 O(1)에 확인할 수 있어요. 메서드는 add · has · delete예요.

🎯 Set 기본 사용법 — 같은 값은 하나만
const s = new Set();

s.add(1);
s.add(2);
s.add(2);   // 이미 있는 값 → 무시됨 (중복 저장 안 함)
s.add(3);

s.size;       // 3   (1, 2, 3 — 2는 하나만!)
s.has(2);     // true
s.delete(2);  // 2 제거
s.has(2);     // false
같은 값을 아무리 여러 번 add해도 하나만 들어가요. 그래서 위에서 size는 4가 아니라 3이에요. 💡 "고유한 값만 모으고 싶다", "이미 본 값인지 확인하고 싶다"면 Set이 정답이에요.
🛠️
코테 3대 활용
배열 탐색 O(n)을 O(1)로 바꾸는 무기
이 셋만 손에 익히면 문제 절반이 쉬워져요.
① 빈도 세기 — 각 요소가 몇 번 나왔나 (Map)
function countFreq(arr) {
  const freq = new Map();
  for (const x of arr) {
    // 이미 있으면 +1, 없으면 0에서 시작해 +1
    freq.set(x, (freq.get(x) || 0) + 1);
  }
  return freq;
}
// ["a","b","a"] → Map { "a" => 2, "b" => 1 }
값을 , 등장 횟수를 으로 쌓아요. 배열을 한 번만 훑으면 O(n)에 모든 빈도를 얻어요.
② 중복 제거 — 배열 → Set (→ 다시 배열)
const arr = [1, 2, 2, 3, 3, 3];
const unique = [...new Set(arr)];   // [1, 2, 3]
배열을 Set에 넣으면 중복이 저절로 사라져요. 다시 배열이 필요하면 [...set]으로 펼쳐요.
③ 존재 확인 — has로 O(1) (예: 두 수의 합)
// two sum: 합이 target인 두 수가 있나?
function hasPair(arr, target) {
  const seen = new Set();
  for (const x of arr) {
    // 짝(target - x)을 이미 봤다면 성공!
    if (seen.has(target - x)) return true;
    seen.add(x);
  }
  return false;
}
배열에서 짝을 이중 반복으로 찾으면 O(n²)이지만, "필요한 짝을 이미 봤는지"를 has로 확인하면 전체가 O(n)이 돼요. 💡 핵심 감각 — "배열을 뒤지는 O(n) 탐색"이 보이면, "Map/Set의 O(1) 조회"로 바꿀 수 있는지 먼저 떠올려보세요. 코테의 단골 패턴이에요.
💥
충돌
다른 키가 같은 위치로? — 그래도 평균 O(1)
개념만 가볍게 잡아둬요.

충돌(collision)서로 다른 키가 해시 함수 계산 결과 같은 위치(버킷)로 가는 상황이에요. 사물함 비유로 치면, 이름은 다른데 같은 번호가 나오는 경우죠.

🔤
체이닝(chaining) — 충돌을 해결하는 대표적인 방법이에요. 같은 버킷에 값이 여러 개 몰리면, 그 칸 안에서 값들을 사슬(chain)처럼 이어 붙여 보관해요(앞서 배운 연결 리스트를 떠올리면 돼요). 꺼낼 땐 그 칸 안의 짧은 사슬만 확인하면 되니, 충돌이 드물면 여전히 빠르게 찾아요.
💥 충돌이 나도 괜찮은 이유 같은 칸에 여러 값이 오면, 그 칸 안에서만 살짝 더 찾으면 돼요(체이닝 등). 해시 함수가 값을 고르게 흩뿌리도록 잘 설계돼 있어서, 충돌은 드물게 일어나요. 그래서 전체적으로는 여전히 평균 O(1)을 유지해요. 💡 이론상 최악의 경우(모든 키가 한 칸에 몰릴 때)는 O(n)이 될 수도 있지만, 코테에서는 대부분 평균 O(1)로 생각하고 풀어도 충분해요.
🧪
이 과목의 실습 랩에서 Map·Set으로 빈도 세기·중복 제거를 직접 짜고 채점해볼 수 있어요. 상단 🧪 실습 버튼에서 열려요. 눈으로 읽는 것보다 손으로 짜면 훨씬 오래 남아요.
🧠 이 장 핵심 요약
📝
문제풀이 · 점검
배운 걸 가볍게 점검해봐요
시험이 아니라 "내가 이해했나" 확인용이에요. 틀려도 바로 해설이 나와요.
🧪
문제를 풀면 즉시 정답과 해설이 나오고, 위쪽 바에 점수가 쌓여요. 손으로 직접 짜보고 싶으면 상단 🧪 실습 랩으로!
CH 06 🔀 정렬 — 데이터를 순서대로, O(n log n)의 세계