[알고리즘] 부분 수열 (w/ 비트 마스크) - 파이썬
2021. 8. 22. 16:51
반응형
🔹 부분 수열 (Subsequence)
부분 수열은 원 수열의 일부 항을 따서 새로 만든 수열이다. (알고리즘 문제를 풀기 위한 수준까지 생각한다)
예를들면,
[1, 2, 3]의 모든 부분 수열은 [ ], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3] 이다.
🔹 부분 수열 만들기
- 완전 검색 기법으로 부분집합을 구한다.
사용된 비트마스크
연산자 | 의미 | 적용 | 적용 의미 |
<< | 피연산자의 비트 열을 왼쪽으로 이동시킨다. |
1 << n | 비트를 십진수로 나타내면 2n 즉, 원소가 n개일 경우의 모든 부분집합 수 |
& | AND 연산을 한다. | i & (1 << j) | i의 j번째 비트가 둘다 1이면 리턴 |
파이썬 코드
def subsequence(arr):
n = len(arr) # 원소의 개수
result_list = [] # 생성된 부분 수열 저장
for i in range(1 << n): # 부분 수열 개수
subset = [] # 부분수열 담기 위함
for j in range(n): # 원소의 수만큼 비트를 비교함
if i & (1 << j):
subset.append(arr[j]) # 부분 수열 만들기
result_list.append(subset)
return result_list
sample_list = [1, 2, 3]
subsequence_list = subsequence(sample_list)
print(subsequence_list)
# [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
🔹 부분 수열 문제 풀기 (BOJ 1182)
보통 부분집합 전체를 구하기 보다는, 특정 조건을 만족하는 부분집합을 구하는 문제가 출제된다.
BOJ 1182 문제는 합이 s가 된는 부분집합 수를 요구한다.
따라서 위 코드에서 구해진 부분집합을 조건문으로 확인하여 알맞는 결과를 이용할 수 있다.
n, s = map(int, input().split()) # 리스트 정수의 개수, 부분 수열의 합
arr = list(map(int, input().split())) # 리스트
cnt = 0 # 조건에 맞는 경우 카운트
for i in range(1 << n):
subset = []
for j in range(n):
if i & (1 << j):
subset.append(arr[j])
if sum(subset) == s:
cnt += 1
if s == 0: # s가 0일경우 공집합을 포함하기때문에, 이 경우를 제외한다.
cnt -= 1
print(cnt)
반응형
'Programming > 알고리즘' 카테고리의 다른 글
[C++] 함수 객체 functor (Function Object) (0) | 2023.04.24 |
---|---|
[C++] Template 이용하기 (Generic 프로그래밍) (0) | 2023.04.24 |
[C++] class와 struct 차이. 무엇을 언제 써야할까? (0) | 2023.04.24 |
[알고리즘] 다양한 정렬 (버블, 카운팅, 선택 정렬) - 파이썬 (0) | 2021.08.22 |
[알고리즘] 시간복잡도 & 공간복잡도 (0) | 2021.08.20 |