유한 개의 정수로 이루어진 집합이 있을 때, 이 집합의 부분집합 중에서 그 집합의 원소를 모두 더한 값이 0이 되는 경우가 있는지 확인하는 알고리즘을 알아보겠습니다.
먼저 문제를 풀기 위한 절차는 아래와 같이 생각해볼 수 있습니다.
- 완전 검색기법으로 모든 부분집합을 구하기
- 부분집합을 모두 더해서 0과 일치하는지 확인해보기
1. 반복문을 이용한 부분집합 구하기
1 | int[] arr = {1, 2, 3, 4} | cs |
- 1이 부분집합에 포함되었을 경우와 안되었을 경우 ( 2가지 )
- 2가 부분집합에 포함되었을 경우와 안되었을 경우 ( 2가지 )
- 3이 부분집합에 포함되었을 경우와 안되었을 경우 ( 2가지 )
- 4가 부분집합에 포함되었을 경우와 안되었을 경우 ( 2가지 )
위의 과정을 개발 코드로 구현해보도록 하겠습니다. bitArr은 인덱스 요소의 표현 여부를 정하는 비트(0, 1)을 저장하고 있습니다. 즉 bitArr[0]의 값이 1이면 arr[0]을 부분집합으로 가지는 것입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public static void main(String[] args) { int[] arr = {1, 2, 3, 4}; int[] bitArr = new int[4]; for(int i=0; i<2; i++) { bitArr[0] = i%2==0 ? 0:1; for(int j=0; j<2; j++) { bitArr[1] = j%2==0 ? 0:1; for(int k=0; k<2; k++) { bitArr[2] = k%2==0 ? 0:1; for(int l=0; l<2; l++) { bitArr[3] = l%2==0 ? 0:1; for(int m=0; m<4; m++) { if(bitArr[m] != 0 ) { System.out.printf(arr[m]+", "); } } System.out.println(""); } } } } } | cs |
위 코드를 이해하기 쉽게 그림으로 일부 표현해 보았습니다. 아래와 같이 진행한다면 네 번째 반복문에는 16개의 (0 0 0 0 ~ 1 1 1 1)의 bitArr 형태를 만들어 낼 것입니다. 각 배열에서 값이 1인 인덱스만 arr[인덱스] 로 출력하면 총 16개의 부분집합을 구할 수 있습니다.
2. 비트연산자를 이용한 부분집합 구하기
- 1 << n 은 원소가 n개일 경우 모든 부분집합의 수
- i & ( 1<< j ) 은 i 의 j번째 인덱스가 0인지 1인지 확인가능
1 2 3 4 5 6 7 8 9 10 11 12 | public static void main(String[] args) { int[] arr = {1, 2, 3, 4}; for(int i=0; i<(1<<4); i++) { for(int j=0; j<4; j++) { if( (i & (1<<j)) >= 1) { System.out.printf("%d, ", arr[j]); } } System.out.println(""); } } | cs |
'알고리즘 > SW Expert Academy' 카테고리의 다른 글
Sort(정렬)에 대해서 - Selection Sort (0) | 2019.02.09 |
---|---|
검색 (0) | 2019.02.09 |
2차원 배열 (0) | 2019.02.03 |
Sort(정렬)에 대해서 (1) - Bubble Sort와 Counting Sort (0) | 2019.01.20 |
탐욕 알고리즘(Greedy Algorithm)을 이용한 Baby-gin (0) | 2019.01.20 |