비트마스크는 선택한 항목들을 숫자 하나에 어떻게 기록하나요?
비트마스크는 고정된 항목들의 선택 여부를 숫자 하나에 담는 방법입니다. 위치 0은 값 1, 위치 1은 값 2처럼 항목마다 겹치지 않는 자리를 배정합니다.
적용 조건·범위: 분석 조건: 20개 위치만 허용합니다. 부분집합 전체를 열거하면 여전히 2^k개 상태입니다.
본문 근거: MDN — Bitwise AND
읽기 전에 알아두면 좋아요
아래 개념이 익숙하면 본문을 바로 읽으세요. 낯선 개념만 링크에서 복습하면 됩니다.
- 기초 구현 패턴: 조건·정수 계산·순회·상태 갱신변수에 값을 담고 조건에 따라 합·개수·최솟값을 갱신하는 기초부터 확인합니다.
개념과 예제는 실행하지 않아도 읽을 수 있습니다. 내 컴퓨터·터미널에서 직접 실행하는 과정은 선택 실습입니다.
과정 위치와 선택 복습 안내
과정 위치: 유량·상태 압축과 계산 복잡도 (선택) · 알고리즘 개념
과정 위치는 이 글이 속한 묶음입니다. 이 단계의 모든 개념을 먼저 읽을 필요는 없습니다. 위에 연결한 개념 중 낯선 내용만 복습하세요. 문제의 조건·상태·갱신 순서는 익숙한 언어로 설명하면 됩니다.
JavaScript로 문법·실행 복습하기 (선택)
개념 글의 코드는 JavaScript 예시입니다. 문제 화면에서는 JavaScript·Python·Java·C++·C# 중 익숙한 언어의 함수를 작성하세요. 본문의 Node.js 입출력 예시는 로컬 실행을 위한 별도 안내입니다.

비트마스크는 고정된 항목들의 선택 여부를 숫자 하나에 담는 방법입니다. 위치 0은 값 1, 위치 1은 값 2처럼 항목마다 겹치지 않는 자리를 배정합니다.
선수 지식: 0과 1의 이진수 표기, 정수와 배열 인덱스를 이해하면 좋습니다.
- 항목 번호와 비트의 위치를 구분합니다.
- 선택 추가·확인·제거를 연산으로 표현합니다.
항목 1과 3을 고르면 2+8이 됩니다
항목 번호를 0부터 매기고 i번 항목의 자리를 1<<i로 정합니다. 1번은 이진수 0010, 3번은 1000입니다. 둘을 선택하면 1010, 십진수 10입니다. 숫자 10 자체가 항목 번호인 것이 아니라 여러 자리의 선택 상태를 합쳐 저장한 값입니다.

| 작업 | 이진 상태 | 십진 값 |
|---|---|---|
| 아무것도 선택하지 않음 | 0000 | 0 |
| 1번 추가 | 0010 | 2 |
| 3번도 추가 | 1010 | 10 |
| 1번 제거 | 1000 | 8 |
특정 자리가 켜져 있는지만 묻는다면 AND 결과가 0인지 확인합니다. 비트 위치와 실제 항목 ID가 다르면 두 값을 연결하는 표도 필요합니다. 예를 들어 도시 ID가 100, 200이라면 이를 그대로 시프트하지 말고 0, 1 같은 작은 인덱스로 대응시킵니다.
추가는 OR, 제거는 AND와 반전입니다
OR는 이미 켜진 자리를 다시 추가해도 그대로 둡니다. XOR는 같은 자리를 두 번 처리하면 꺼지므로 “반드시 추가”가 아니라 “선택 상태 뒤집기”에 알맞습니다. 제거할 때는 해당 비트만 0인 마스크와 AND합니다. 없는 항목을 제거해도 나머지 선택은 바뀌지 않습니다.

코드는 mask와 slot을 매번 검사합니다. 전체 마스크를 받고 특정 비트만 바꾸는 함수가 입력 범위를 검사하지 않으면 음수나 소수도 비트 연산 과정에서 다른 값으로 바뀔 수 있습니다. 이 예제의 계약은 20개 위치, 0~19이며 선택 집합에 없는 다른 비트는 허용하지 않습니다.
JavaScript Number의 비트 연산은 큰 정수 저장소가 아닙니다
Number에 쓰는 AND·OR·시프트는 32비트 정수 변환을 따릅니다. 부호 자리까지 무심코 사용하면 양수로 기대한 결과가 음수가 될 수 있고, 시프트 횟수도 임의의 큰 자리로 확장되지 않습니다. 여기서 20개라는 제한은 학습 예제와 이후 상태 수를 관리하기 위한 선택입니다. 언어가 비트를 20개만 지원한다는 뜻은 아닙니다.

항목이 많거나 ID가 드문드문 있으면 Set이 더 읽기 쉬울 수 있습니다. BigInt 비트 연산을 사용할 수도 있지만 Number와 섞을 수 없으며 예제 전체의 숫자형 계약을 바꿔야 합니다. 항목을 마스크로 압축해도 가능한 부분집합 수 2의 n제곱이 작아지는 것은 아닙니다.
전체 코드와 직접 실행
개념을 읽었다면 아래 예제를 직접 실행하며 상태 변화를 확인할 수 있습니다.
전체 JavaScript 코드와 실행 방법 펼치기
별도 패키지는 필요하지 않습니다. Node.js가 처음이라면 브라우저와 Node.js 시작 안내부터 확인하세요.
bitmask-selected-set.mjs 파일을 만들고 아래 전체 코드를 저장합니다.
function checkMask(mask) {
if (!Number.isInteger(mask) || mask < 0 || mask >= 2 ** 20) {
throw new RangeError('mask는 20비트의 음이 아닌 정수여야 합니다.');
}
}
function checkSlot(slot) {
if (!Number.isInteger(slot) || slot < 0 || slot >= 20) {
throw new RangeError('위치는 0부터 19까지입니다.');
}
}
function addFlag(mask, slot) {
checkMask(mask); checkSlot(slot);
return mask | (1 << slot);
}
function removeFlag(mask, slot) {
checkMask(mask); checkSlot(slot);
return mask & ~(1 << slot);
}
function hasFlag(mask, slot) {
checkMask(mask); checkSlot(slot);
return (mask & (1 << slot)) !== 0;
}
function selectedIds(mask) {
checkMask(mask);
const result = [];
for (let slot = 0; slot < 20; slot++) if (hasFlag(mask, slot)) result.push(slot);
return result;
}
const selected = addFlag(addFlag(0, 1), 3);
console.log(selected);
console.log(JSON.stringify(selectedIds(selected)));
console.log(removeFlag(selected, 1));
파일이 있는 폴더의 터미널에서 실행합니다.
node bitmask-selected-set.mjs
기대 출력
10
[1,3]
8
비용과 적용 범위
시간: 예제의 단일 추가·확인·제거는 고정 폭의 O(1), 전체 선택 목록은 위치 수 k에 대해 O(k)입니다.

공간: 마스크는 O(1), 선택 목록을 반환하면 O(k)까지 필요합니다.
분석 조건: 20개 위치만 허용합니다. 부분집합 전체를 열거하면 여전히 2^k개 상태입니다.
직접 확인해 보기
현재 값 10에서 3번 항목이 선택됐는지 확인하고 3번을 제거하면 얼마인가요?

답과 이유 확인
10 & 8은 8이므로 선택돼 있습니다. 3번을 제거하면 2가 남아 1번만 선택된 상태입니다.
함께 읽을 글
- Map·Set으로 값 조회와 중복 제거 — 같은 선택 집합을 Set으로 표현하는 방법과 비교합니다.
- 기초 구현 패턴 — 반복에서 어떤 값을 보관하고 갱신하는지 먼저 익힙니다.
참고 자료
- MDN — Bitwise AND — Number 비트 연산의 32비트 변환을 확인합니다. 예제는 부호 비트를 피하는 20개 위치만 허용합니다.
이 글이 도움이 되었나요?
이어서 공부하기
체크포인트: 예제의 상태 변화를 손으로 추적하고 아래 문제에 적용하세요. 값이 없는 경우와 원소 하나인 경우도 설명해 보세요. 작은 기준 풀이와 비교하고 경로 복원·역방향 취소·입력 크기에 따른 비용을 설명하세요.
다음 추천 · 알고리즘 개념: 외판원 문제: 모든 방문 순서를 비교하고 출발점으로 돌아오기
권장 순서는 학습 가이드와 같습니다. 다른 순서는 접힌 참고 목록에서 확인할 수 있습니다. 읽음 표시는 숙달이나 채점 결과가 아닙니다.
원래 과정 목록 순서 (선택)
읽음 기록
읽음 — / 전체 30개 · 필수 0개
새 글 받아보기
RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.