smooth waters run deep

공부내용/알고리즘

부분집합

yeon_11 2020. 11. 8. 15:13

부분집합을 구하는 방법 중 재귀함수와 비트연산자를 이용하는 방법은 다음과 같다.

 

 

재귀함수 이용

 

예: 집합 {a, b, c, d}에서 {a,b}는 a,b는 포함되어 있고 c,d는 포함되어 있지 않다.

 

포함안될 때와 될 때 두 가지 경우를 checked[]배열에 표시하고, 재귀함수로 돌린다.

즉, 각 원소에 대하여, (포함X, 포함X, 포함X, 포함X) ~ (포함O, 포함O, 포함O, 포함O) 까지를 모두 탐색한다.

 

public static void main(String[] args) {
	String[] arr = {"a", "b", "c", "d"};
	boolean[] checked = new boolean[arr.length]; //포함여부 체크

	makeset1(arr, checked, 0); // 1.재귀함수 이용
}

private static void makeset1(String[] arr, boolean[] checked, int index){

	if(index >= arr.length){
		for(int i=0; i<arr.length; i++){
			if(checked[i])
				System.out.print(arr[i]+" ");
		}
		System.out.println();
		return;
	}

	checked[index] = false; //arr[index]가 포함안될 때
	makeset1(arr, checked, index+1);

	checked[index] = true; //arr[index]가 포함될 때
	makeset1(arr, checked, index+1);
        
}

 

 

 

 

비트 이동 연산자 <<,>> 이용

 

   - 비트 이동 연산자 란?

 

 X의 비트를 Y만큼 오른쪽/왼쪽으로 이동시키는 '비트를 이동시키는 연산자' 이다.

 

       

예시)

 


public static void main(String[] args) {
	String[] arr = {"a", "b", "c", "d"};

	makeset2(arr); // 2.비트 연산자 이용
}

private static void makeset2(String[] arr){

	for(int i=0; i < (1<<arr.length); i++){ // (1)
		for(int j=0; j<arr.length; j++){ // (2)
			if((i & (1<<j)) != 0){ // (3)
				System.out.print(arr[j]+" ");
			}
		}
		System.out.println();
	}
    
}

(1) 1<<arr.length == 1<<4 이므로, 1111을 왼쪽으로 4비트 이동한 수 이다.

    즉 0000 ~ 1111 까지의 경우를 탐색한다.

 

(2) arr.length는 비트 자리수를 의미한다.

    arr = {a,b,c,d} 인 경우에 - a,b,c,d를 비트로 나타내면 0000~1111까지 표현할 수 있고,

    표현에 따르면 arr.length=4의 비트 자리수를 갖는다.

    그러므로 비트 자리수만큼 탐색한다.

 

(3) 1<<j 는 0001, 0010, 0100, 1000 을 의미한다.

    0000~1111 을 0001, 0010, 0100, 1000 과 각각 AND 해서 나온 수가 0이 아니면 출력한다.

    공집합인 경우 == i=0000일 때를 제외하고 arr의 부분집합이 모두 출력된다.

 

 

'공부내용 > 알고리즘' 카테고리의 다른 글

최대공약수 & 최소공배수  (0) 2020.11.22
조합 nCr  (0) 2020.11.11
순열 nPr  (0) 2020.11.11
카운팅 정렬 (Counting Sort)  (0) 2020.11.03
소수  (0) 2020.10.20