[Java] 프로그래머스 > 2021 Dev-Matching: 웹 백엔드 개발자(상반기) > 다단계 칫솔 판매 with 자바

: ) YOUNG·2022년 5월 10일
2

알고리즘

목록 보기
126/422
post-thumbnail

문제

https://programmers.co.kr/learn/courses/30/lessons/77485


각 판매원의 이름을 담은 배열 enroll, 각 판매원을 다단계 조직에 참여시킨 다른 판매원의 이름을 담은 배열 referral, 판매량 집계 데이터의 판매원 이름을 나열한 배열 seller, 판매량 집계 데이터의 판매 수량을 나열한 배열 amount가 매개변수로 주어질 때, 각 판매원이 득한 이익금을 나열한 배열을 return 하도록 solution 함수를 완성해주세요. 판매원에게 배분된 이익금의 총합을 계산하여(정수형으로), 입력으로 주어진 enroll에 이름이 포함된 순서에 따라 나열하면 됩니다.



생각하기

이번 문제는 이해하는데 시간이 꽤걸리고, 문제를 풀고나서 11, 12, 13번을 해결하느라 시간을 많이 투자했다.
HashMap자료구조를 잘만 이용한다면 쉽게 풀 수 있다.

동작

    	int len = enroll.length;
    	for(int i=0; i<len; i++) {
    		memberMap.put(enroll[i], referral[i]);
    		result.put(enroll[i], 0);
    	}
  
    	len = amount.length;
    	for(int i=0; i<len; i++) {
    		distribution(seller[i], amount[i]*100);
    	}

먼저 전체 피라미드 구조의 회원들을 Map자료구조로 memberMap을 만들어준다.
자식이 벌은 금액의 10%를 부모에게 나눠주는 모습이여서 Key를 자식 Value를 부모로 만들었다.

그리고 selleramount 배열은 같은 길이의 값을 가지는 세트이므로,
하나의 반복문으로 실행해서 값을 구할 수 있도록 했다.


    static void distribution(String name, int amount) {
  
    	// 판매한 본인이 먼저 값을 가져감
    	String par = "";
    	int rest = amount / 10;
    	int pay =  amount - rest;
    	if(result.containsKey(name)) {
    		result.put(name, result.get(name) + pay); 
    		par = memberMap.get(name);
    	}
  
    	// 1080 -> 180 -> 11 -> 1
    	while( !par.equals("-") ) {
  
    		int total = rest;
    		if(total < 1) {
    			return;
    		}
  
        	rest = total / 10;
        	pay =  total - rest;
    		result.put(par, result.get(par) + pay);
    		par = memberMap.get(par); 
    	} 
  
    } // End of distribution

distribution 메소드에서는 seller 배열의 수익을 올린 판매자 이름과, amount배열의 금액을 매개변수로 가져와서 피라미드 구조에서 가져가는 금액을 계산하도록 만들었다.

가장먼저 들어오는 수익을 올리는 인원name은 전체 수익금의 90%를 가져간다.

여기서 실수를 했던 부분이 restamount 0.1로 해주고 payamount 0.9로 해주었는데, 이렇게 하면 double형이 되고 소수점 아래를 반올림 해야하는 상황이 오게되는데, 만약 그렇게 되면 반올림이 되지 않았을 때 오류가 발생하게 된다.

그래서 amount / 10으로 수정해주었다.

이후 미리 만들어놓은 전체 멤버 수익금의 결과값을 담을 result Map에서 각자 이름을 key값으로 벌은 금액을 찾아 새로 Map에 넣는 구조를 만들어 주었다.
쉽게 말하자면, result에 있는 금액의 값을 수정해가는 방식으로 만들었다.

계속해서 memberMap의 구조를 타고 타고 넘어가서 자식과 부모의 연결고리를 찾도록 해주었다.

Ex)
<자식1, 부모1> (자식key값으로 찾은 부모가 다시 다른 사람의 자식이 됨) -> <자식, 부모> -> ....

이 과정을 반복하다가 par인 부모가 "-"가 되면 탈출한다.


    	len = result.size();
    	int[] answer = new int[len];
    	for(int i=0; i<len; i++) {
    		answer[i] = result.get(enroll[i]);
    	}
  
        return answer;

이후에 마지막에 result Map에서 enroll의 이름을 순서대로 불러와서 value를 추출한뒤 answer배열에 넣기만 하면 끝이다.






코드


import java.util.*;
  
class Solution {
	static HashMap<String, String> memberMap = new HashMap<>(); // 자식 key, 부모 value
	static HashMap<String, Integer> result = new HashMap<>();
  
    public int[] solution(String[] enroll, String[] referral, String[] seller, int[] amount) {
    	int len = enroll.length;
    	for(int i=0; i<len; i++) {
    		memberMap.put(enroll[i], referral[i]);
    		result.put(enroll[i], 0);
    	}
  
    	len = amount.length;
    	for(int i=0; i<len; i++) {
    		distribution(seller[i], amount[i]*100);
    	}
  
    	len = result.size();
    	int[] answer = new int[len];
    	for(int i=0; i<len; i++) {
    		answer[i] = result.get(enroll[i]);
    	}
  
        return answer;
    } // End of solution
  
    // 자식의 부모를 찾고, 또 다시 해당 부모가 자식이 되어 부모를 찾는 방식
    // 마지막에 value가 '-'일 경우 return 
    static void distribution(String name, int amount) {
  
    	// 판매한 본인이 먼저 값을 가져감
    	String par = "";
    	int rest = amount / 10;
    	int pay =  amount - rest;
    	if(result.containsKey(name)) {
    		result.put(name, result.get(name) + pay); 
    		par = memberMap.get(name);
    	}
  
    	// 1080 -> 180 -> 11 -> 1
    	while( !par.equals("-") ) {
  
    		int total = rest;
    		if(total < 1) {
    			return;
    		}
  
        	rest = total / 10;
        	pay =  total - rest;
    		result.put(par, result.get(par) + pay);
    		par = memberMap.get(par); 
    	} 
  
    } // End of distribution
   
} // End of Solution class

0개의 댓글