역추적 문제입니다.
https://ksb-dev.tistory.com/109 에 역추적 문제 예제가 있으니 역추적을 잘 모르시는 분은 한 번 읽어보시기 바랍니다.
역추적의 기본 개념은 간단합니다.
배열에 부모의 위치를 저장하여 재귀적으로 부모를 찾아가는 방법입니다.
private static int find(int po) {
if(parents[po] == po){
return po;
}
return find(parents[po]);
}
어디선가 많이 본 코드 아닌가요?
네, 유니온-파인드(Union-Find)에서의 그 파인드 입니다.
https://ksb-dev.tistory.com/114 에 유니온 파인드를 잘 정리해 놨으니 잘 모르시는 분은 읽어보시기 바랍니다.
파인드를 사용하기 위해서는 기본적으로 부모의 위치와 자신의 위치의 숫자가 필요합니다.
문제에서 딱히 나와있지는 않지만, 중복된 이름이 없다고 가정하여 map을 사용하고 각 이름에 숫자를 부여했습니다.
map을 사용하면 O(1)의 시간 복잡도로 get을 할 수 있습니다.
또, find 연산을 위해 자기 자신의 위치를 배열에 저장했습니다.
for (int i = 0; i < enroll.length; i++) {
map.put(enroll[i], i+1);
parents[i] = i;
}
문제에서 referral은 자기 자신의 부모를 의미합니다.
map에서 이름을 통해 부모 위치를 가져옵니다.
단, "-"는 아무도 추천하지 않았지만 그림에서 알 수 있듯이 Center의 자식이므로 최상위 위치인 0을 저장합니다.
(0의 위치는 민호. 즉, Center을 의미합니다.)
for (int i = 0; i < referral.length; i++) {
String s = referral[i];
if (s.equals("-")) {
parents[i+1] = 0;
} else {
parents[i+1] = map.get(s);
}
}
seller와 amount를 통해 판매자와 판매 개수를 통해 부모를 역추적합니다.
find를 하여 부모를 재귀적으로 찾아가고 부모에게 줄 값을 전달합니다.
주의해야 할 점은 올림(ceil)연산을 통해야 1의 자리 계산이 제대로 동작합니다.
private static int find(int po, int mo) {
if(parents[po] == po){
return po;
}
money[po-1] += Math.ceil(mo*0.9);
return find(parents[po], (int)(mo*0.1));
}
money[po-1]을 하는 이유는 money배열에 민호(Center)가 포함되지 않기 때문입니다.
문제의 결과는 민호를 제외한 사람들이 얻는 금액을 요구하기 때문입니다.
[구현 코드]
import java.util.HashMap;
import java.util.Map;
class Solution {
private static Map<String, Integer> map;
private static int[] parents, money;
public static int[] solution(String[] enroll, String[] referral, String[] seller, int[] amount) {
map = new HashMap<>();
parents = new int[enroll.length + 1];
money = new int[enroll.length];
for (int i = 0; i < enroll.length; i++) {
map.put(enroll[i], i+1);
parents[i] = i;
}
for (int i = 0; i < referral.length; i++) {
String s = referral[i];
if (s.equals("-")) {
parents[i+1] = 0;
} else {
parents[i+1] = map.get(s);
}
}
for (int i = 0; i < seller.length; i++) {
String person = seller[i];
int po = map.get(person);
int mo = amount[i] * 100;
find(po, mo);
}
return money;
}
private static int find(int po, int mo) {
if(parents[po] == po){
return po;
}
money[po-1] += Math.ceil(mo*0.9);
return find(parents[po], (int)(mo*0.1));
}
}
'알고리즘' 카테고리의 다른 글
백준 - 10282 해킹(Java) (0) | 2022.10.04 |
---|---|
프로그래머스 - 거리두기 확인하기(Java) (0) | 2022.10.03 |
프로그래머스 - 행렬 테두리 회전하기(Java) (0) | 2022.10.02 |
프로그래머스 - 로또의 최고 순위와 최저 순위(Java) (0) | 2022.10.02 |
프로그래머스 - 길 찾기 게임(Java) (0) | 2022.09.30 |