본문 바로가기
카테고리 없음

[hash, 이진탐색 LV2] 시소 짝꿍 JS

by limew 2023. 10. 4.

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


 

문제요점

  • 4,3,2 축 2,3,4
  • 시소짝꿍: 몸무게*거리가 같으면
  • 몇쌍 짝꿍존재?
  • (보충) 짝꿍끼리의 순서는 상관없다. (시소의 오른쪽, 왼쪽 중 어디에 앉는지는 구별하지 않음)

풀이

  • 2,3,4를 통해 가능한 조합을 만든다
    • 짝꿍끼리의 순서는 상관없으므로 왼쪽무게 중심으로 가능한 오른쪽 무게를 찾고 그 갯수를 더한다
    • 왼쪽 중심으로 가능한 오른쪽무게는 왼쪽무게의 *1, *3/2, *2, *4/3이다
      • 왼쪽이 2, 오른쪽 2일때 => 1:1 => 오른쪽은 왼쪽의 1배
      • 왼쪽이 2, 오른쪽 3일때 => 2:3 => 오른쪽은 왼쪽의 3/2배
      • 왼쪽이 2, 오른쪽 4일때 => 1:2 => 오른쪽은 왼쪽의 2배
      • 왼쪽이 3, 오른쪽 4일때 => 3:4 => 오른쪽은 왼쪽의 4/3배
  • 몸무게마다 갯수를 hash로 정리
  • 왼쪽을 기준으로 더 큰 무게(오른쪽)를 찾아야하니까 몸무게를 오름차순 sort한다
  • weights를 순회하며 왼쪽 몸무게가 각 weight일 때마다 가능한 오른쪽 몸무게가 있으면 answer에 추가한다
    • left, right 같은 몸무게이면 자신을 제외한 갯수를 추가한다
    • 다른 가능한 몸무게가 존재하면 갯수를 추가한다
    • 짝꿍끼리의 순서는 상관없으므로 다음차례에선 현재무게를 비교대상에서 제외시킨다.

 

 

각 weight마다 위 4가지 비율의 무게를 구한 뒤 weights에 있는지 찾아봐야하는데 hash 를 사용하면 빠르다 o(1)

hash에 각 무게가 있음 answer에 더해준다

ab = ba는 같다. 이처럼 짝꿍끼리의 순서는 상관없으므로 다음차례에선 현재무게를 비교대상에서 제외시킨다.

 

전체코드

function solution(weights) {
    var answer = 0;
    const hash = {}; // {weight: count} 수가 존재하는지 O(1)로 찾기위해 해쉬를 썼다.
    for (const w of weights) {
        hash[w] = (hash[w] || 0 ) + 1;
    }
    weights.sort((a, b) => a-b);
    
    for (const w of weights) {
        if (hash[w] > 1) answer += hash[w]-1; // 자신과 똑같은 수가 있으면, 자신을 제외한 짝꿍의 수를 더한다.
        if (hash[w*3/2] > 0) answer += hash[w*3/2]; // 자신보다 3/2배 큰 수가 있음 그 수만큼 더한다
        if (hash[w*2] > 0) answer += hash[w*2]; // 자신보다 2배 큰 수가 있음 그 수 만큼 더한다.
        if (hash[w*4/3] > 0) answer += hash[w*4/3];
        
        hash[w] -= 1; // 짝꿍끼리의 순서는 상관없다 따라서 다음차례에서 현재 w를 비교대상에서 제외시킨다
    }
    return answer;
}

 

 

또 다른 풀이

 

unction solution(weights) {
  var answer = 0;
  const possibles = [1, 3 / 2, 2, 4 / 3];
  const obj = {};
  weights.forEach((weight) => {
    obj[weight] = (obj[weight] || 0) + 1;
  });
  weights.sort((a, b) => a - b);

  for (const leftW of weights) {
    for (const p of possibles) {
      const rightW = leftW * p;

      // 같은 몸무게이면
      if (leftW === rightW) {
        answer += obj[leftW] - 1; // 자신을 제외한 몸무게 갯수를 더한다
      } else if (obj[rightW]) {
        answer += obj[rightW]; // 가능한 몸무게의 갯수를 더한다
      }
    }
    obj[leftW]--; 
  }
  return answer;
}