코딩테스트-알고리즘/프로그래머스

[프로그래머스/Lv.1] 가장 많이 받은 선물

닉네임생각즁 2024. 1. 16. 18:41

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

 

프로그래머스

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

programmers.co.kr

 

결과내기까지 굉장히 복잡한거같아서 중간중간 남기고 출력확인하면서 풀었다

아래는 그 과정

 

1. 선물 주고받은거 map에 넣기

        for(int i=0; i<gifts.length; i++) {
            map.put(gifts[i], map.getOrDefault(gifts[i], 0) +1);
        }
        System.out.println(map);

 

 

2. 선물지수 계산하기 위해 각각 map에 넣기

        Map<String,Integer> giveList = new HashMap<>(); // key 준 사람, value 횟수
        Map<String,Integer> takeList = new HashMap<>(); // key 받은 사람, value 횟수 
        for(int i=0; i<gifts.length; i++) {
            String[] gift = gifts[i].split(" ");
            System.out.println("선물 준 사람 : " + gift[0] + ", 선물 받은 사람 : " + gift[1]);
            
            giveList.put(gift[0], giveList.getOrDefault(gift[0], 0) +1);
            takeList.put(gift[1], takeList.getOrDefault(gift[1], 0) +1);
            
        }
        System.out.println("선물 준 리스트 : " + giveList);
        System.out.println("선물 받은 리스트 : " + takeList);

 

 

3. 선물 지수 계산

        // 선물 지수 계산하기 
        Map<String,Integer> giveList = new HashMap<>(); // key 준 사람, value 횟수
        Map<String,Integer> takeList = new HashMap<>(); // key 받은 사람, value 횟수 
        Map<String,Integer> giftNum = new HashMap<>(); // 선물 지수 : key 사람, value 준횟수-받은횟수 
        for(int i=0; i<gifts.length; i++) {
            String[] gift = gifts[i].split(" ");
            //System.out.println("선물 준 사람 : " + gift[0] + ", 선물 받은 사람 : " + gift[1]);
            
            giveList.put(gift[0], giveList.getOrDefault(gift[0], 0) +1);
            takeList.put(gift[1], takeList.getOrDefault(gift[1], 0) +1);
            
        }
        //System.out.println("선물 준 리스트 : " + giveList);
        //System.out.println("선물 받은 리스트 : " + takeList);
        
        for(int i=0; i<friends.length; i++) {
            giftNum.put(friends[i], giveList.getOrDefault(friends[i], 0) - takeList.getOrDefault(friends[i], 0));
        }
        System.out.println("선물 지수 : " + giftNum);

예제에서 보여주는 선물 지수랑 값 다 똑같음!

 

 

4. 

짝지어진 친구들 이름을 어딘가에 담고 뽑아와서 비교해주는걸 어떻게 해야할지 안떠올라서 힘들게 돌고돌다가 friends 배열이 갑자기 눈에 들어왔다 존재 자체를 잊고 있었는데!!! 이거와 map을 이용하면 나올거 같아서 작성해보고 출력해서 눈으로 확인해봤다

해당 이름 순서대로 선물을 주고받았다면 횟수가 나오고, 그렇지 않으면 null이 나옴

거의 다온게 느껴져서 행복😚😚😚

 

 

5. 비교해주면서 계산

import java.util.*;

class Solution {
    public int solution(String[] friends, String[] gifts) {
        int answer = 0;
        int[] result = new int[friends.length]; // 선물 결과 담을 배열
        Map<String,Integer> map = new HashMap<>();
        for(int i=0; i<gifts.length; i++) {
            map.put(gifts[i], map.getOrDefault(gifts[i], 0) +1); // gifts 정리
        }
        //System.out.println(map);
        
        // 선물 지수 계산하기 
        Map<String,Integer> giveList = new HashMap<>(); // key 준 사람, value 횟수
        Map<String,Integer> takeList = new HashMap<>(); // key 받은 사람, value 횟수 
        Map<String,Integer> giftNum = new HashMap<>(); // 선물 지수 : key 사람, value 준횟수-받은횟수 
        

        
        for(int i=0; i<gifts.length; i++) {
            String[] gift = gifts[i].split(" ");
            //System.out.println("선물 준 사람 : " + gift[0] + ", 선물 받은 사람 : " + gift[1]);
            
            giveList.put(gift[0], giveList.getOrDefault(gift[0], 0) +1);
            takeList.put(gift[1], takeList.getOrDefault(gift[1], 0) +1);
            
        }
        //System.out.println("선물 준 리스트 : " + giveList);
        //System.out.println("선물 받은 리스트 : " + takeList);
        
        for(int i=0; i<friends.length; i++) {
            giftNum.put(friends[i], giveList.getOrDefault(friends[i], 0) - takeList.getOrDefault(friends[i], 0));
        }
        //System.out.println("선물 지수 : " + giftNum);
        
        System.out.println(map);
        //System.out.println(map.get(friends[0] + " " + friends[1]));
        //System.out.println(map.get(friends[0] + " " + friends[2]));
        
        int n1 = -1; // [i] -> [i+1] 횟수 담아줄 수
        int n2 = -1; // [i+1] -> [i] 횟수 담아줄 수
        for(int i=0; i<friends.length-1; i++) {
            for(int j=i+1; j<friends.length; j++) {
                String s1 = friends[i] + " " + friends[j];
                String s2 = friends[j] + " " + friends[i];
                System.out.println(s1 + " " + s2);
                if(map.get(s1) != null) {
                    n1 = map.get(s1); // i->j 횟수
                }  
                if(map.get(s2) != null) {
                    n2 = map.get(s2); // j->i 횟수
                } 
                
                if(n1 != -1 && n2 != -1) { // 서로 주고받은 경우
                    if (n1 > n2) result[i] += 1; // n1이 크면 인덱스i 친구에게 선물+1
                    else if (n1 < n2) result[j] += 1; // n2가 크면 인덱스j 친구에게 선물+1
                    else { // 주고받은 선물 횟수 같은 경우
                        if (giftNum.get(friends[i]) > giftNum.get(friends[j])) result[i] += 1;
                        else if (giftNum.get(friends[i]) < giftNum.get(friends[j])) result[j] += 1;
                        // 선물 지수 같은 경우는 처리x
                    }
                } else if(n1 == -1 && n2 != -1) { // i는 안주고 j는 줌
                    result[j] += 1;           
                } else if(n1 != -1 && n2 == -1) { // i는 주고 j는 안줌
                    result[i] += 1;           
                } else if(n1 == -1 && n2 == -1) { // 서로 안 주고 받음
                    if (giftNum.get(friends[i]) > giftNum.get(friends[j])) result[i] += 1;
                    else if (giftNum.get(friends[i]) < giftNum.get(friends[j])) result[j] += 1;
                    // 선물 지수 같은 경우는 처리x
                }
            }
        }

        int max = Integer.MIN_VALUE;                                   
        for(int i=0; i<result.length; i++) {
            System.out.println(result[i]);
            max = Math.max(max, result[i]);
        }

        
        return max;
    }

}

 

 

1번 실패 / 2,3번 통과

 

 

주어지는대로 짝도 잘 지어지고 비교도 하고있는듯한데 계산이 뭔가 잘못나온다

 

.

.

여기에서 시간을 엄청 날렸다 해결하고싶어서 쉬는시간마다 계속 확인하고 조금씩 바꿔봐도 1번 테스트가 절대 통과를 안하는거다ㅠㅠㅠ

 

-> 결국 수업 끝날쯤에 챗지피티한테 물어봤고 실수를 알아낼 수 있었다

완전 사소한 실수였다

 

        int n1 = -1; // [i] -> [i+1] 횟수 담아줄 수
        int n2 = -1; // [i+1] -> [i] 횟수 담아줄 수
        for(int i=0; i<friends.length-1; i++) {
            for(int j=i+1; j<friends.length; j++) {
                String s1 = friends[i] + " " + friends[j];
                String s2 = friends[j] + " " + friends[i];

 

 

        for(int i=0; i<friends.length-1; i++) {
            for(int j=i+1; j<friends.length; j++) {
                int n1 = -1; // [i] -> [i+1] 횟수 담아줄 수
                int n2 = -1; // [i+1] -> [i] 횟수 담아줄 수
                String s1 = friends[i] + " " + friends[j];
                String s2 = friends[j] + " " + friends[i];

 

내 코드에서는 n1과 n2를 -1로 설정해놓은게 조건을 가르는 중요한 요소이다 주거나 받은 내역이 없다면 값이 -1로 남아있기때문에 이거로 주고받았는지 여부를 확인할 수 있다..!

근데 내가 이 값들의 초기화를 for문 밖에 해줬기 때문에 두번째 for문부터는 -1로 초기화되어있는게 아니라 그 전 for문을 돌았을때 얻었던 n1, n2값이 되어있던거다 당연히 틀릴수밖에ㅠㅠㅠ 

그래서 for문안으로 옮겼고 새로 돌때마다 초기화를 시켜줬다.............그리고 드디어 맞았다!!!!!!

엄청 어이없는 실수로 헤맸지만 다음에는 비슷한 실수를 절대 하지 않기 위해 연습한거라고 생각하려한다😥😥

 

 

 

최종 코드

import java.util.*;

class Solution {
    public int solution(String[] friends, String[] gifts) {
        int answer = 0;
        int[] result = new int[friends.length]; // 선물 결과 담을 배열
        Map<String,Integer> map = new HashMap<>();
        for(int i=0; i<gifts.length; i++) {
            map.put(gifts[i], map.getOrDefault(gifts[i], 0) +1); // gifts 정리
        }
        //System.out.println(map);
        
        // 선물 지수 계산하기 
        Map<String,Integer> giveList = new HashMap<>(); // key 준 사람, value 횟수
        Map<String,Integer> takeList = new HashMap<>(); // key 받은 사람, value 횟수 
        Map<String,Integer> giftNum = new HashMap<>(); // 선물 지수 : key 사람, value 준횟수-받은횟수 
        

        
        for(int i=0; i<gifts.length; i++) {
            String[] gift = gifts[i].split(" ");
            //System.out.println("선물 준 사람 : " + gift[0] + ", 선물 받은 사람 : " + gift[1]);
            
            giveList.put(gift[0], giveList.getOrDefault(gift[0], 0) +1);
            takeList.put(gift[1], takeList.getOrDefault(gift[1], 0) +1);
            
        }
        //System.out.println("선물 준 리스트 : " + giveList);
        //System.out.println("선물 받은 리스트 : " + takeList);
        
        for(int i=0; i<friends.length; i++) {
            giftNum.put(friends[i], giveList.getOrDefault(friends[i], 0) - takeList.getOrDefault(friends[i], 0));
        }
        //System.out.println("선물 지수 : " + giftNum);
        
        System.out.println(map);
        //System.out.println(map.get(friends[0] + " " + friends[1]));
        //System.out.println(map.get(friends[0] + " " + friends[2]));
        

        for(int i=0; i<friends.length-1; i++) {
            for(int j=i+1; j<friends.length; j++) {
                int n1 = -1; // [i] -> [i+1] 횟수 담아줄 수
                int n2 = -1; // [i+1] -> [i] 횟수 담아줄 수
                String s1 = friends[i] + " " + friends[j];
                String s2 = friends[j] + " " + friends[i];
                System.out.println(s1 + " " + s2);
                if(map.get(s1) != null) {
                    n1 = map.get(s1); // i->j 횟수
                }  
                if(map.get(s2) != null) {
                    n2 = map.get(s2); // j->i 횟수
                } 
                
                if(n1 != -1 && n2 != -1) { // 서로 주고받은 경우
                    if (n1 > n2) result[i] += 1; // n1이 크면 인덱스i 친구에게 선물+1
                    else if (n1 < n2) result[j] += 1; // n2가 크면 인덱스j 친구에게 선물+1
                    else { // 주고받은 선물 횟수 같은 경우
                        if (giftNum.get(friends[i]) > giftNum.get(friends[j])) result[i] += 1;
                        else if (giftNum.get(friends[i]) < giftNum.get(friends[j])) result[j] += 1;
                        // 선물 지수 같은 경우는 처리x
                    }
                } else if(n1 == -1 && n2 != -1) { // i는 안주고 j는 줌
                    result[j] += 1;           
                } else if(n1 != -1 && n2 == -1) { // i는 주고 j는 안줌
                    result[i] += 1;           
                } else if(n1 == -1 && n2 == -1) { // 서로 안 주고 받음
                    if (giftNum.get(friends[i]) > giftNum.get(friends[j])) result[i] += 1;
                    else if (giftNum.get(friends[i]) < giftNum.get(friends[j])) result[j] += 1;
                    // 선물 지수 같은 경우는 처리x
                }
            }
        }

        int max = Integer.MIN_VALUE;                                   
        for(int i=0; i<result.length; i++) {
            System.out.println(result[i]);
            max = Math.max(max, result[i]);
        }

        
        return max;
    }

}

 

 

출력 없애고 주석 정리한 최종_최종_코드

import java.util.*;

class Solution {
    public int solution(String[] friends, String[] gifts) {
        int[] result = new int[friends.length]; // 선물 결과 담을 배열
        
        Map<String,Integer> map = new HashMap<>(); // gifts 정리 (같은 값 묶고 개수 세기)
        for(int i=0; i<gifts.length; i++) {
            map.put(gifts[i], map.getOrDefault(gifts[i], 0) +1);
        }
        
        
        Map<String,Integer> giveList = new HashMap<>(); // key : 준 사람, value : 횟수
        Map<String,Integer> takeList = new HashMap<>(); // key : 받은 사람, value : 횟수 
        
        for(int i=0; i<gifts.length; i++) {
            String[] gift = gifts[i].split(" ");
            giveList.put(gift[0], giveList.getOrDefault(gift[0], 0) +1);
            takeList.put(gift[1], takeList.getOrDefault(gift[1], 0) +1);
        }
    
        
        Map<String,Integer> giftNum = new HashMap<>(); // 선물 지수 - key : 사람, value 준횟수-받은횟수 
        
        for(int i=0; i<friends.length; i++) {
            giftNum.put(friends[i], giveList.getOrDefault(friends[i], 0) - takeList.getOrDefault(friends[i], 0));
        }

        // 다음달 선물 결과 계산
        for(int i=0; i<friends.length-1; i++) {
            for(int j=i+1; j<friends.length; j++) {
                int n1 = -1; // [i] -> [i+1] 횟수 담아줌
                int n2 = -1; // [i+1] -> [i] 횟수 담아줌
                String s1 = friends[i] + " " + friends[j];
                String s2 = friends[j] + " " + friends[i];

                if(map.get(s1) != null) {
                    n1 = map.get(s1); // i->j 횟수
                }  
                if(map.get(s2) != null) {
                    n2 = map.get(s2); // j->i 횟수
                } 
                
                
                // 서로 주고받은 경우
                if(n1 != -1 && n2 != -1) {
                    if (n1 > n2) result[i] += 1; // n1이 크면 인덱스i 친구에게 선물+1
                    else if (n1 < n2) result[j] += 1; // n2가 크면 인덱스j 친구에게 선물+1
                    else { // 주고받은 선물 횟수 같은 경우
                        if (giftNum.get(friends[i]) > giftNum.get(friends[j])) result[i] += 1;
                        else if (giftNum.get(friends[i]) < giftNum.get(friends[j])) result[j] += 1;
                        // 선물 지수 같은 경우는 처리x
                    }
                
                // 서로 주고받지 않은 경우
                } else if(n1 == -1 && n2 != -1) { // i는 안주고 j는 줌
                    result[j] += 1;           
                } else if(n1 != -1 && n2 == -1) { // i는 주고 j는 안줌
                    result[i] += 1;           
                } else if(n1 == -1 && n2 == -1) { // 서로 선물 x
                    if (giftNum.get(friends[i]) > giftNum.get(friends[j])) result[i] += 1;
                    else if (giftNum.get(friends[i]) < giftNum.get(friends[j])) result[j] += 1;
                    // 선물 지수 같은 경우는 처리x
                }
            }
        }

        // 최대값이 정답
        int max = Integer.MIN_VALUE;                                   
        for(int i=0; i<result.length; i++) {
            System.out.println(result[i]);
            max = Math.max(max, result[i]);
        }
        return max;
    }
}

 

굉장히 보람찬 과정이었다

근데 코드가 솔직히 너어ㅓㅓㅓㅓㅓ무 지저분하다 더 간단하게 풀 수 있는 방법이 있는지 알고싶다

만약 효율성테스트까지 있는 문제였다면 실패하지않았을까ㅋㅋㅋㅋㅋㅋㅋㅋㅋ 

 

 

✔ 답 낼 때 필요한 것들이 엄청 많고 복잡한거같아서 주석으로 구분해주고 출력 결과를 중간중간 확인하면서 진행했다 확인없이 다 적고나서 답을 확인하면 어디서 틀린지 확인하기 어려웠는데 어디까지는 맞는 코드라는 확신이 있으니 좋았다 도움이 많이 됐다!!

 getOrDefault() 는 짱이다 hashMap과 getOrDefault() 를 알게 된건 신의 한수👍👍 대신에 좀 쉽게 풀 수 있는데도 이걸 먼저 떠올려서 더 복잡하게 푼 문제도 있었다 적절한떄에 쓰는 연습도 해야함

 

 

완전 최신 문제 푼거라 괜히 기분좋고 뿌듯😎😎