250x250
Notice
Recent Posts
Recent Comments
관리 메뉴

탁월함은 어떻게 나오는가?

[Algorithm] 롤케이크 자르기 ( Programmers - JavaScript ) 본문

[Snow-ball]프로그래밍(컴퓨터)/Algorithm Training

[Algorithm] 롤케이크 자르기 ( Programmers - JavaScript )

Snow-ball 2023. 12. 26. 21:55
반응형

문제 설명

철수는 롤케이크를 두 조각으로 잘라서 동생과 한 조각씩 나눠 먹으려고 합니다. 이 롤케이크에는 여러가지 토핑들이 일렬로 올려져 있습니다. 철수와 동생은 롤케이크를 공평하게 나눠먹으려 하는데, 그들은 롤케이크의 크기보다 롤케이크 위에 올려진 토핑들의 종류에 더 관심이 많습니다. 그래서 잘린 조각들의 크기와 올려진 토핑의 개수에 상관없이 각 조각에 동일한 가짓수의 토핑이 올라가면 공평하게 롤케이크가 나누어진 것으로 생각합니다.

 

예를 들어, 롤케이크에 4가지 종류의 토핑이 올려져 있다고 합시다. 토핑들을 1, 2, 3, 4와 같이 번호로 표시했을 때, 케이크 위에 토핑들이 [1, 2, 1, 3, 1, 4, 1, 2] 순서로올려져 있습니다. 만약 세 번재 토핑(1)과 네 번째 토핑(3) 사이를 자르면 롤케이크의 토핑은 [1, 2, 1], [3, 1, 4, 1, 2]로 나뉘게 됩니다. 철수가 [1, 2, 1]이 놓인 조각을, 동생이 [3, 1, 4, 1, 2]가 놓인 조각을 먹게 되면 철수는 두가지 토핑(1, 2)을 맛볼 수 있지만, 동생은 네 가지 토핑(1, 2, 3, 4)을 맛볼 수 있으므로, 이는 공평하게 나누어진 것이 아닙니다. 만약 롤케이크의 네 번째 토핑(3)과 다섯 번째 토핑(1) 사이를 자르면 [1, 2, 1, 3], [1, 4, 1, 2]로 나뉘게 됩니다. 이 경우 철수는 세가지 토핑 (1, 2, 3)을, 동생도 세 가지 토핑(1, 2, 4)을 맛볼 수 있으므로, 이는 공평하게 나누어진 것입니다. 공평하게 롤케이크를 자르는 방법은 여러가지 일 수 있습니다. 위의 롤케이크를 [1, 2, 1, 3, 1], [4, 1, 2]으로 잘라도 공평하게 나뉩니다. 어떤 경우에는 롤케이크를 공평하게 나누지 못할 수도 있습니다.

 

롤케이크에 올려진 토핑들의 번호를 저장한 정수 배열 topping이 매개변수로 주어질 때, 롤케이크를 공평하게 자르는 방법의 수를 return 하도록 solution 함수를 완성해주세요.

 

 

 

 


 

 

 

제한사항

 

 

 

 


 

 

 

입출력 예

 

 

 


 

 

 

입출력 예 설명

 

 

 


 

 

 

문제풀이

이번 "롤케이크 자르기" 문제를 풀기 위해서 new Map(), new Set()을 사용했다. 사실 이번 문제를 풀때 loop를 1번만 돌려서 풀려고 접근했었다. 하지만 왠걸 시간초과가 발생했다. 아마도 splite 함수로 인한 것이라고 추정된다.

 

일단 실패했던 문제풀이에 대해 설명하자면, 매우 간단하다. 문제의 핵심은 결국 토핑의 갯수를 공평하게 나누기만 하면 되는것이다. 몇조각과 상관이 없다.

 

그렇기 때문에 예를들어, [1, 2, 1, 3, 1, 4, 1, 2]의 배열이 존재한다면 loop는

[1] vs [2, 1, 3, 1, 4, 1, 2] 부터 [1, 2, 1, 3, 1, 4, 1] vs [2]까지 나누고 그것들을 중복이 되지 않는 set으로 만들어 size 비교하는 것이다. 그렇지만 시간초과로 아래의 코드는 패스!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function solution(topping) {
  let answer = 0;
 
  for (let i = 0; i < topping.length - 1++i) {
    const [frontArr, backArr] = splitIntoChunk(topping, i + 1);
    const frontSet = new Set(frontArr);
    const backSet = new Set(backArr);
 
    if (frontSet.size === backSet.size) answer++;
  }
 
  return answer;
}
 
function splitIntoChunk(arr, chunk) {
  const copyArr = [...arr];
  const result = [];
 
  const tempArray = copyArr.splice(0, chunk);
  result.push(tempArray);
  result.push(copyArr);
 
  return result;
}
cs

 

 

 

그래서 접근한 방식이 아래와 같은 방식이다. 성공한 풀이에서는 단일 loop 를 2개를 사용하였다. loop 2개를 실행해도 여전히 O(n)이기 때문이다. 

 

첫번째 loop에서는 케이크 토핑의 전체 갯수를 체크를 하기 위해서 사용하였다.

 

그리고, topping을 하나씩 상대방에게 주는 방식으로 loop를 사용하면서 sendingSet과 receivingSet 의 size를 비교하여 토핑숫자가 같을 때를 체크하였다. 그리고 그 아이디어를 기반한 코드는 아래와 같다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function solution(topping) {
  let answer = 0;
  const cakeTable = new Map();
  const sendingSet = new Set(topping);
 
  for (let i = 0; i < topping.length++i)
    cakeTable.set(topping[i], (cakeTable.get(topping[i]) || 0+ 1);
 
  const receivingSet = new Set();
  topping.forEach((tp) => {
    if (cakeTable.get(tp) >= 1) {
      cakeTable.set(tp, cakeTable.get(tp) - 1);
      receivingSet.add(tp);
    }
 
    if (!cakeTable.get(tp)) {
      cakeTable.delete(tp);
      sendingSet.delete(tp);
    }
 
    if (receivingSet.size === sendingSet.size) answer++;
  });
 
  return answer;
}
cs

 

 

 

 

 

 

 

 

 

 

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

 

프로그래머스

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

programmers.co.kr

 

반응형
Comments