완전탐색 문제를 풀기위해 필수적으로 알아야되는 순열, 조합, 부분집합, 다음순열의 개념과 간략화한 알고리즘을 정리하려고 한다.
순열, 조합, 부분집합, 다음순열에서 공통적으로 사용할 변수와 의미는 다음과 같다.
int N : 선택의 후보가 될 수 있는 N개의 수
int M : 선택하고자 하는 원소의 수
int cnt : 재귀 호출 내에서 해당 시점에서 선택한 원소의 수를 의미
boolean[] isSelected : 재귀 수행 중 과거에 해당 원소를 이미 선택을 했는지 판단하기 위한 boolean 배열
int[] selectedArr : 선택한 원소를 저장할 int 배열
순열은 주어진 숫자들의 순서를 고려하여 조합을 만들기 때문에 아래 두 가지를 체크해야한다.
// 1 ~ N 사이의 값 중에 M개 뽑기
 public void permutation(int cnt) {
 	if (cnt == M) {
    	    // 순열을 완성했을 때 처리할 로직
            return;
  	}
    	for (int i = 0; i < N; i++) {
    	    if (isSelected[i]) continue;
            selectedArr[cnt] = i + 1;
            isSelected[i] = true;
            permutation(cnt + 1);
            isSelected[i] = false;
        }
 }
            조합은 주어진 숫자들의 순서를 고려하지 않고 조합을 만들기 때문에 순열처럼 선택 여부를 확인할 필요가 없다. 조합을 함수를 호출 할 때 현 시점에서 선택한 인덱스 + 1의 값을 매개변수로 넘겨주어 항상 다음 수 부터 선택하도록 구현할 수 있다.
// 1 ~ N 사이의 값 중에 M개 뽑기
 public void combination(int cnt, int index) {
 	if (cnt == M) {
    	    // 조합을 완성했을 때 처리할 로직
            return;
  	}
    	for (int i = index; i < N; i++) {
    	    selectedArr[cnt] = i + 1;
            combination(cnt + 1, i + 1);
        }
 }
            집합의 원소들을 선택, 비선택하는 과정을 통해 공집합을 포함한 각기 다른 부분집합을 구할 수 있다.
// 1 ~ N 사이의 값 중에 M개 뽑기
 public void subset(int cnt) {
 	if (cnt == M) {
    	    for (int i = 0; i < M; i++) {
            	if (isSelected[i]) {
                   // 완성된 부분집합에 포함된 요소이면 
                }
            }
    	    // 조합을 완성했을 때 처리할 로직
            return;
  	}
    	isSelected[cnt] = true; // 선택
       	subset(cnt + 1);
        isSelected[cnt] = false; // 비선택
       	subset(cnt + 1);
 }
            작성중