CodeingTestPrac/Java Coding Test

[프로그래머스] 후보키 Java 조합 - 재귀 , 백트래킹

sung.hyun.1204 2023. 8. 28. 14:10

 

파이썬을 이용한 코딩테스트시 간단하게 라이브러리를 호출하여 조합을 뽑아내는 것 이 가능했지만 자바는 직접구현을 해야한다.

 

숫자 4가 주어졌을때 

1 , 2, 3,4 , (1,2),(1,3) ,,,, (1,2,3,4) 와 같은 숫자를 출력하는 코드를 짜보자.

 

n = 4 일때  , nCr 을 구현하니 변수 r 도 필요하다.

 

재귀를 사용하며 , 배열의 크기와 r 이 같으면 탈출 하는 조건문을 추가해준다.

 

@Test
    public void combination_test() {
        int n = 4;
        var s = showCombination(n);
        System.out.println(s);
    }
    List<Set<Integer>> answer = new ArrayList<>();
    public int showCombination(int n) {
        for(int r = 1 ; r <= n ;r++){
            generateCombination(n,r);
        }
        return n ;
    }
    public void generateCombination(int n ,int r) {
        List<Integer> combination = new ArrayList<>();
        generate(n,r,1,combination);
    }
    public void generate(int n ,int r ,int start , List<Integer> combiantion){
        if(combiantion.size() ==r){
            System.out.println(combiantion);
            return;
        }
        for(int i = start ; i <= n ; i++){
            combiantion.add(i);
            generate(n,r,i+1,combiantion);
            combiantion.remove(combiantion.size() -1);
        }
    }

출력은 다음과 같다.

 

[1]
[2]
[3]
[4]
[1, 2]
[1, 3]
[1, 4]
[2, 3]
[2, 4]
[3, 4]
[1, 2, 3]
[1, 2, 4]
[1, 3, 4]
[2, 3, 4]
[1, 2, 3, 4]

 

 

@Test
    public void combination_less_method_test() {
        int n = 4 ;
        List<List<Integer>> combinations = new ArrayList<>();
        combine(n,1,new ArrayList<>(),combinations);
        for(List<Integer> combination : combinations){
            System.out.println(combination);
        }
    }
    public void combine(int n , int start  , List<Integer> current , List<List<Integer>> combinations) {
        if(!current.isEmpty()) {
            combinations.add(new ArrayList<>(current));
        }
        for(int i = start ; i <= n; i++) {
            current.add(i);
            combine(n,i+1,current,combinations);
            current.remove(current.size() -1);
        }
    }

 

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 4]
[1, 3]
[1, 3, 4]
[1, 4]
[2]
[2, 3]
[2, 3, 4]
[2, 4]
[3]
[3, 4]
[4]

 

 

위의 개념을 적용할 문제는 다음과 같다.

 

프로그래머스 후보키 문제이다.

https://school.programmers.co.kr/learn/courses/30/lessons/42890

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

위의 방식을 이용한 풀이이다.

 

1차 풀이에서 틀린 이유 

 

1. Set

(1,2)

(2,1)

로 주어진 자료에서 만약 Set 을 사용한다면

(1,2)

(1,2)

 

이되어 중복으로  나온다.

 

2. 얇은 복사

정답을 가지는 전역 변수 2 차원 배열인 answList 에 다음과 같이 추가하면

 

func( arr ) {

   answList.add(arr) ;

}

 

얇은 복사로 배열이 추가가되어 , arr이 변경시 정답 배열 내부의 값도 바뀐다.

 

func( arr ) {

   answList.add(new ArrayList(arr)) ;

}

 

새로 배열을 선언해주자.

import java.util.*;
class Solution {
    List<List<Integer>> anwSets = new ArrayList<>();
    List<List<String>> relMap = new ArrayList<>();
    int row = 0;

    public int solution(String[][] relation) {
        row = relation.length;
        int column = relation[0].length;
        for (int i = 0; i < column; i++) {
            List<String> tmp = new ArrayList<>();
            for (int j = 0; j < row; j++) {
                tmp.add(relation[j][i]);
            }
            relMap.add(tmp);
        }
        int n = column;
        for (int r = 1; r <= column; r++) {
            genCombi(n, r);
        }
        int answer = anwSets.size();
        System.out.println(anwSets);
        return answer;
    }

    private void genCombi(int n, int r) {
        List<Integer> arr = new ArrayList<>();
        generateCom(n, r, 0, arr);
    }

    private void generateCom(int n, int r, int start, List<Integer> arr) {
        if (r == arr.size()) {
            
            for(List<Integer> sets : anwSets) {
                if(arr.containsAll(sets)) return;
            }

            List<List<String>> tmparr = new ArrayList<>();
            for (int i = 0; i < row; i++) {
            List<String> aRow = new ArrayList<>();
                for (Integer item : arr) {
                    String element = relMap.get(item).get(i);
                    aRow.add(element);
                }
                if (tmparr.contains(aRow))
                    return;
                tmparr.add(aRow);
            }

            if (tmparr.size() == row) {
                anwSets.add(new ArrayList<>(arr));
            }
            return;
        }
        for (int i = start; i < n; i++) {
            arr.add(i);
            generateCom(n, r, i + 1, arr);
            arr.remove(arr.size() - 1);
        }
    }
}