배열의 길이가 10만이 넘기 때문에 이중으로 순회하면서 카운트하는 것은 당연히 불가능하고
weight를 먼저 순회하면서 각 weight와 매칭될 수 있는 가상의 몸무게를 Map에 저장해 풀어야 하는 컨셉이다.
public static void main(String[] args) {
int[] arr = new int[]{100,180,360,100,270};
System.out.print(solution(arr));
}
public static Long solution(int[] weights) {
Arrays.sort(weights);
Map<Double, Integer> map = new HashMap<>();
Long result = 0L;
for(int weight : weights) {
double case1 = weight*1.0;
double case2 = weight*2.0/3;
double case3 = weight*1.0/2;
double case4 = weight*3.0/4;
result += map.getOrDefault(case1,0);
result += map.getOrDefault(case2,0);
result += map.getOrDefault(case3,0);
result += map.getOrDefault(case4,0);
map.put(weight*1.0, map.getOrDefault(weight*1.0,0)+1);
}
return result;
}
배열을 sorting을 먼저 하여 작은 수가 먼저 오게 한 다음, 자신보다 같거나 작은 weight의 케이스를 먼저 찾는다. (작은 수에서 큰 수로 순회하기 때문에 자신보다 큰 수를 찾도록 하면 찾을 수 없다.) 큰 weight의 입장에서 자기보다 작은 짝궁만 찾기 때문에 중복은 발생하지 않는다.
자신과 같은 몸무게인 경우에 대한 처리에 애를 먹었다. 처음엔 헷갈리지 않도록 weight을 한 번 순회하며 자신에게 해당하는 모든 케이스를 먼저 map에 집어넣은 뒤 다시한 번 weight을 순회하며 자신을 필요로 하는 상대를 카운트하였으나, 자신과 중복인 weight이 존재하는 경우 제대로된 카운트가 이뤄지지 않았다.
정답은 map에 자신을 넣기 전에, 자신과 짝이 될 수 있는 케이스를 맵에서 먼저 찾아보고 카운트한 뒤 자신을 map에 넣는다. 이렇게 하면 같은 weight을 가진 정수들이 차례로 들어오며 짝궁이 될 수 있는 케이스가 자연스럽게 카운팅된다 (같은 weight가 총 4명 있는 경우 => 0 + 1 + 2 + 3)