본문 바로가기
기초수학

조합 (Combination)

by devnyang 2024. 2. 27.
반응형

조합


서로 다른 n 개 중 r개를 선택하는 경우의 수 (순서 x, 중복 x)

ex) 서로 다른 4명 중 주번 2명 뽑기

조합식

        int n = 4;
        int r = 2;

        int pResult = 1;   //순열 구하기
        for (int i = n; i >= n- r +1; i--) {
            pResult *= i;
        }

        int rResult = 1;  //r!구하기
        for (int i = 1; i <= r ; i++) {
            rResult *= i;
        }
        System.out.println("결과: " + pResult/ rResult); // 순열/r!

 

중복 조합


서로 다른 n개 중 r개를 선택하는 경우의 수.

단, 이 때에는 (순서 x, 중복 o)

중복조합식1

 static int getCombination(int n, int r) {
        int pResult = 1;  //순열 구하기
        for (int i = n; i >= n- r +1; i--) {
            pResult *= i;
        }

        int rResult = 1;  //r! 구하기
        for (int i = 1; i <= r ; i++) {
            rResult *= i;
        }
        return pResult/rResult;  //순열/r!
    }
    
    //중복조합 구하기
        n = 2;
        r = 3;

        System.out.println("결과: " + getCombination(n+r-1, r));

 

 

ex) 후보 2, 유권자 3명일 때의 무기명 투표

중복조합식2

 

 


1,2,3,4 이용 => 세자리 자연수 만들기

public class Practice {
    void combination(int[] arr, boolean[] visited, int depth, int n, int r) {

        if(r == 0){
            for (int i = 0; i < n; i++) {
                if(visited[i]) {
                    System.out.print(arr[i] + " ");
                }
            }
            System.out.println();
            return;
        }
        if(depth == n) {
            return;
        }

        visited[depth] = true;
        combination(arr,visited, depth+1, n, r-1);

        visited[depth] = false;
        combination(arr,visited,depth+1,n,r);

    }
    
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4};
        boolean[] visited = {false, false, false, false};

        Practice p = new Practice();
        p.combination(arr, visited, 0, 4, 3);
    }
}

 

 

하나하나 살펴보자.

        int[] arr = {1, 2, 3, 4};  //배열생성
        boolean[] visited = {false, false, false, false};  //visited배열 생성

        Practice p = new Practice();  //객체 생성
        p.combination(arr, visited, 0, 4, 3);  //메서드 combination 호출
        //depth = 0, n = 4, r = 3

 

        visited[depth] = true;
        combination(arr,visited, depth+1, n, r-1);

방문했다는 흔적을 위해 visited를 true로 바꿔줌. visited[0] = 1이 된다. combination(arr, visited, 1,4,2)를 호출한다.

(depth : 1,  r : 2)

 

        visited[depth] = true;
        combination(arr,visited, depth+1, n, r-1);

if 문에서 해당사항이 없으므로 쭉 내려와서 visited[depth] 는 2, r은 1이 되어 한번 더 호출된다.

visited[3]은 1 , depqth : 3,  r : 0이 된다. 

r이 0이 됐으므로 if 문이 시행된다.

        if(r == 0){
            for (int i = 0; i < n; i++) {
                if(visited[i]) {
                    System.out.print(arr[i] + " ");
                }
            }
            System.out.println();
            return;
        }
        if(depth == n) {
            return;
        }

if문에서 n이 4이므로 i는 3까지 진행되고 visited[i]가  true일 때 arr[i]가 출력된다. 따라서 123이 출력되고 다시 return한다.

결과 : 123

 

        visited[depth] = true;
        combination(arr,visited, depth+1, n, r-1); // 여기로 return

        visited[depth] = false;  //진행
        combination(arr,visited,depth+1,n,r);

다음이 진행되어 vistied[3] = 0(현재 1,1,0,0)이 되고 combination(arr,visited,2+1,4,1)을  호출한다.

반복하여 다시 visited : {1,1,0,1} 이 된다. 그리고 combination(arr,visited, 3+1, 4, 1-1)을 호출한다.

 

        if(r == 0){  //여기에 걸림.
            for (int i = 0; i < n; i++) {
                if(visited[i]) {
                    System.out.print(arr[i] + " ");
                }
            }
            System.out.println();
            return;
        }
        if(depth == n) {
            return;
        }

다시 r 이 0이므로 if문에 걸려 visited가 true인 것을 출력하고 return한다.  결과 : 124

 

        visited[depth] = true;
        combination(arr,visited, depth+1, n, r-1);  //여기로 return

        visited[depth] = false;
        combination(arr,visited,depth+1,n,r);

아래를 진행하여 visited : {1,1,0,0}이 된다. 그리고 combination을 호출한다. 이때 depth는 3, r은 1

따라서, combination(arr,visited, 4,4,1)로 호출된다.

 

      if(r == 0){
            for (int i = 0; i < n; i++) {
                if(visited[i]) {
                    System.out.print(arr[i] + " ");
                }
            }
            System.out.println();
            return;
        }
        if(depth == n) {  //여기에 걸림.
            return;
        }

depth 랑 n이 같으므로 다시 return 된다.

 

        visited[depth] = true;
        combination(arr,visited, depth+1, n, r-1);

        visited[depth] = false; 
        combination(arr,visited,depth+1,n,r); //여기로 리턴!

이대로 한번 끝나고 다시 depth 가 1일때로 돌아가서 visited[depth] = false;부터 다시 반복한다.

 

결과

1 2 3 
1 2 4 
1 3 4 
2 3 4
반응형

'기초수학' 카테고리의 다른 글

제곱과 로그  (0) 2024.02.27
점화식(Recurrence), 재귀함수  (0) 2024.02.27
순열(Permutation), 팩토리얼(Factorial)  (0) 2024.02.27
경우의 수 (합의 법칙, 곱의 법칙)  (0) 2024.02.26
집합(Set)이란?  (0) 2024.02.26