노트

빈도수 세기 패턴

Frequency Counter Pattern

CS#algorithm · 연결된 개념 6개

쉽게 말하면

빈도수 세기는 개표할 때 후보마다 바를 정 자를 그어 가며 세는 방식이에요. 표 하나하나를 다른 표와 맞대 보지 않고 한 번만 훑으니, 두 목록 비교가 훨씬 빨라져요.

비유가 깨지는 곳 개표판에서 이름 칸을 바로 찾는 일이 빠른 건 해시 테이블 조회가 평균 O(1)이라서예요. 빈도를 배열의 indexOf로 찾으면 다시 O(n²)이 돼요.

값이 몇 번 나오는지를 객체나 Map에 모아 두고 비교하는 풀이 패턴. 배열이나 문자열끼리 비교할 때 생기기 쉬운 중첩 반복 O(n²)을 O(n)으로 줄인다.

// 두 문자열이 같은 글자들로 이루어졌는가(애너그램, Anagram)
function isAnagram(a: string, b: string) {
  if (a.length !== b.length) return false
  const count = new Map<string, number>()
  for (const ch of a) count.set(ch, (count.get(ch) ?? 0) + 1)
  for (const ch of b) {
    const n = count.get(ch)
    if (!n) return false // 없거나 이미 다 썼다
    count.set(ch, n - 1)
  }
  return true
}
  • 한쪽으로만 빈도표를 만들고 다른 쪽을 순회하며 깎아 나가면 표를 하나만 써도 된다
  • 길이를 먼저 비교하면 깎은 뒤 남은 값을 다시 확인할 필요가 없다
  • 원리는 해시 테이블의 평균 O(1) 조회다. 배열의 indexOf로 찾으면 다시 O(n²)이 된다
  • 실무에서도 같은 생각을 자주 쓴다. 목록을 id로 묶어 두고 조회하거나, 중복을 Set으로 거른다(빅오 표기법, 파이썬 기본 컬렉션)

다른 패턴은 알고리즘 문제 풀이 접근법.

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 언어적 안티패턴

    이름, 타입, 주석이 말하는 것과 코드가 실제로 하는 일이 어긋나는 것. 읽는 사람을 잘못된 추측으로 이끈다.

  • 이진 탐색

    정렬된 배열에서 가운데 값과 찾는 값을 비교해 매번 절반을 버리며 찾는 방법. 원소가 100만 개여도 20번 남짓이면 끝난다(O(log n)). 처음부터 하나씩 확인하는 선형 탐색(Linear Search)은 O(n)이다.

  • 동적 프로그래밍

    복잡한 문제를 더 작은 부분 문제로 나눠 풀되, 한 번 푼 부분 문제의 답을 저장해 다시 계산하지 않는 방법. 두 조건이 맞을 때 쓴다.

  • 디자인 패턴

    반복해서 나타나는 설계 문제에 대한 검증된 해결 구조와 그 이름. 복사해 쓰는 완성 코드가 아니라 객체들이 협력하는 방식을 설명하는 어휘다. 1994년 이른바 GoF(Gang of Four, 네 명의 저자)의 책 『Design Patterns: Elements of Reusable Object-Oriented Software』가 23개 패턴을 정리하며 널리 퍼졌다.

  • 비밀번호 저장: 인코딩·암호화·해싱

    비밀번호는 원문으로 저장하지 않고, 느린 단방향 해시(one-way hash)로 바꿔 저장한다. 로그인할 때는 입력값을 같은 방식으로 해시해 저장된 값과 비교한다. 인코딩·암호화·해싱은 비슷해 보이지만 목적이 다르다.

보기 옵션