간편 조합

{A,B,C,D} 4개의 원소중 3개를 뽑을 조합은 어떻게 될까?

조합은 뽑은 원소가 중복되면 안되기 때문에 앞에서부터 차례대로 원소를 뽑아본다.

단순하게 for 를 3번 돌면 된다.

// 4개중 3개를 뽑을경우

int n = 4;

for(int i=0;i<n;i++)

for(int j=i+1;j<n;j++)

for(int k=j+1;k<n;k++){

System.out.print(array[i]+" "+array[j]+" "+array[k]);

System.out.println();

}

결과

A B C

A B D

A C D

B C D


2개를 뽑을땐 for를 2번 반복, 4개를 뽑을땐 for를 4번 반복한다. 몇 개를 뽑을지 모르는데 매번 이렇게 할 수 없다. 또한 for 문이 비슷하게 반복되지 않는가.

코드를 잘 보면 for 한번이 원소 하나를 고르는 행위를 하는 것임을 알 수 있다.

그렇다면 for문으로 원소 한개를 고르고 다시 자기 자신을 호출해 남은일을 넘기는 재귀를 구성해본다. 

위 for 문이 몇개를 뽑을지에 따라 반복된다. 즉 n개중 r개를 뽑는다면 for 는 r만큼 반복되어야 한다.

하나를 뽑으면 그다음에 뽑을 수 있는 개수는 한개 줄어든다. 그렇게 뽑다가 뽑을 수 있는 개수가 0이 되면 r개만큼 뽑은것이다. 더이상 뽑지 않고 출력한다.

이후에는 마지막에 뽑았던 것을 빼놓고 다음에 뽑을 수 있는 것을 뽑는다. 다음것도 뽑을 것이 없다면 다음것을 뽑을 수 있을때까지 마지막을 뺀다. 


조합의 작업을 다음 입력들의 집합으로 정의한다.

1. 원소들의 총 개수

2. 더 골라야 할 원소들의 개수

3. 지금까지 고른 원소들의 번호

위 3가지를 고려해 for 반복 for 문 작업을 하는 재귀함수로 구성한다.


import java.util.Stack;


public class Combination_1 {

static char array[] = {'A','B','C','D'};

public static void main(String[] args) {

Stack<Integer> st = new Stack<Integer>();

for(int i=1; i<=array.length; i++){

System.out.println(i+"개 뽑을경우 조합");

pick(array.length, st, i);

}

}

static void pick(int n,Stack<Integer> st,int r){

if(r==0)

printPick(st);

int smallest = st.isEmpty() ? 0 : st.lastElement() + 1; 

for(int next = smallest; next < n; next++){

st.push(next);

pick(n,st,r - 1);

st.pop();

}

}

static void printPick(Stack<Integer> st){

for(int i:st)

System.out.print(array[i]+" ");

System.out.println();

}

}

결과 

1개 뽑을경우 조합

2개 뽑을경우 조합

A B 

A C 

A D 

B C 

B D 

C D 

3개 뽑을경우 조합

A B C 

A B D 

A C D 

B C D 

4개 뽑을경우 조합

A B C D 

'SW > 알고리즘' 카테고리의 다른 글

내리막길  (0) 2017.09.13
위상정렬 Topological sort  (0) 2017.08.18
이진탐색 binary search  (0) 2017.08.08
재귀호출 Recursive call  (0) 2017.01.22
삼각형의 넓이  (0) 2017.01.13

+ Recent posts