ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스] 후보키 Java 조합 - 재귀 , 백트래킹
    CodeingTestPrac/Java Coding Test 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);
            }
        }
    }
Designed by Tistory.