[프로그래머스] 롤케이크 자르기 Lv2
2025. 1. 9. 16:11ㆍ코딩 테스트 준비
728x90
반응형
https://school.programmers.co.kr/learn/courses/30/lessons/132265?language=javascript
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제 설명
철수는 롤케이크를 두 조각으로 잘라서 동생과 한 조각씩 나눠 먹으려고 합니다.
이 롤케이크에는 여러가지 토핑들이 일렬로 올려져 있습니다. 철수와 동생은 롤케이크를 공평하게 나눠먹으려 하는데,
그들은 롤케이크의 크기보다 롤케이크 위에 올려진 토핑들의 종류에 더 관심이 많습니다. 그래서 잘린 조각들의 크기와
올려진 토핑의 개수에 상관없이 각 조각에 동일한 가짓수의 토핑이 올라가면 공평하게 롤케이크가 나누어진 것으로
생각합니다.
예를 들어, 롤케이크에 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 함수를 완성해주세요.
제한사항
1 ≤ topping의 길이 ≤ 1,000,000
1 ≤ topping의 원소 ≤ 10,000
처음 문제를 보고 분명 자르는 위치와 상관없이 배열에 존재하는 토핑의 개수를 카운팅하고 이를 반복문으로 나누는게 방법이라는 것은 캐치했다.
하지만 아무리 생각해도 반복문으로 slice를 해서 중첩으로 반복하게되면 시간 초과가 뜰 가능성이 높다고 생각했고, 이를 해결할 방법을 떠올리지 못했다.
결국 해답을 찾아야했고 그 중 가장 직관적인게 아래의 코드였다.
function solution(topping) {
// 1) 전체 토핑별 개수가 담긴 Map 객체를 생성한다.
const map = new Map();
// 2) 형의 토핑의 종류를 담을 Set 객체 생성한다.
const bro = new Set();
// 3) 형과 동생이 케이크를 공평하게 나누어지는 횟수
let answer = 0;
// 4) Map에 토핑별 개수를 담는다.
for(let i=0; i<topping.length; i++){
map.has(topping[i]) ? map.set(topping[i], map.get(topping[i])+1) : map.set(topping[i], 1);
}
// 5) 토핑의 개수 만큼 반복한다.
for(let i=0; i<topping.length; i++){
// 6) Map에 담긴 토핑을 하나씩 빼고 형에게 준다.
let count = map.get(topping[i])-1;
bro.add(topping[i]);
// 7) 토핑의 개수가 0이 되면 삭제하고, 남아 있으면 하나씩 뺀다.
count === 0 ? map.delete(topping[i]) : map.set(topping[i], count);
/*
8) Map에 남아있는 토핑의 종류가 곧 동생의 토핑의 종류이기 때문에
형의 토핑의 개수와 동생의 토핑의 개수를 비교하여 같으면 answer를 증가시킨다.
*/
if(bro.size === map.size) answer++;
}
// 9) 총 공평하게 나누어지는 횟수를 return한다.
return answer;
}
코드 작동 방식
- Map 객체 생성
- map은 전체 토핑별 개수를 저장하는 객체입니다.
- Map은 키-값 쌍으로 데이터를 저장하며, 각 토핑의 이름을 키로, 해당 토핑의 개수를 값으로 저장합니다.
- Set 객체 생성
- bro는 형이 가진 토핑의 종류를 저장하는 객체입니다.
- Set은 중복을 허용하지 않는 고유한 값의 집합입니다. 형이 가진 토핑의 종류를 효율적으로 추적하는 데 사용됩니다.
- 전체 토핑 개수를 map에 저장
- map.has(topping[i]): 이미 map에 토핑이 존재하는지 확인합니다.
- 존재하면 값(토핑 개수)을 1 증가시키고, 존재하지 않으면 새로운 토핑으로 추가합니다.
- 형과 동생의 토핑을 나누는 작업
- 한 바퀴씩 반복하며 토핑을 형에게 나눠줍니다:
- bro.add(topping[i]): 형의 토핑에 추가합니다. Set 객체이므로 중복이 제거됩니다.
- map.get(topping[i]) - 1: 동생이 가진 해당 토핑 개수를 1 줄입니다.
- 토핑 개수가 0이 되면 map.delete(topping[i])로 동생의 토핑 목록에서 제거합니다.
- 형과 동생의 토핑 종류를 비교:
- bro.size === map.size: 형이 가진 토핑의 종류 수와 동생이 가진 토핑의 종류 수가 같으면 공평하게 나눠진 것으로 판단하고, answer를 증가시킵니다.
- 한 바퀴씩 반복하며 토핑을 형에게 나눠줍니다:
- 결과 반환
- 공평하게 나눌 수 있는 횟수를 반환합니다.
Map과 Set의 차이점
특성MapSet
데이터 저장 방식 | 키-값 쌍(key-value)으로 저장합니다. | 고유한 값만 저장합니다. |
키 | 모든 데이터 타입이 키로 사용 가능(number, string, etc.) | 고유값으로만 저장되며, 중복을 허용하지 않습니다. |
값 | 각 키에 연결된 값은 중복 가능 | 고유값만 저장되므로 중복된 값은 저장되지 않습니다. |
데이터 접근 | map.get(key)로 키를 통해 값에 접근합니다. | 직접 값을 확인하거나(set.has(value)), 이터레이터 사용 |
주요 메서드 | set(key, value), get(key), delete(key) | add(value), delete(value), has(value) |
용도 | 데이터와 그에 연관된 정보를 저장할 때 사용됩니다. | 고유한 값의 집합을 관리할 때 사용됩니다. |
이 코드에서의 Map과 Set 활용
- Map
- 동생의 토핑 목록을 관리하기 위해 사용됩니다.
- 각 토핑의 이름(키)과 해당 토핑의 개수(값)를 저장합니다.
- 동생이 가진 토핑의 개수를 효율적으로 업데이트하거나 삭제할 수 있습니다.
- Set
- 형이 가진 토핑의 종류를 관리하기 위해 사용됩니다.
- 중복된 토핑을 제거하고, 형이 가진 토핑의 고유한 종류만 추적할 수 있습니다.
예제
실행 과정:
- 초기 map 내용:
Map(4) { 1 => 3, // 토핑 1: 3개 2 => 2, // 토핑 2: 2개 3 => 2, // 토핑 3: 2개 4 => 1 // 토핑 4: 1개 }
- 각 반복 단계:
- 첫 번째 반복: 형이 1을 가짐 → bro = {1}, map = {1 => 2, 2 => 2, 3 => 2, 4 => 1}
- 두 번째 반복: 형이 2를 가짐 → bro = {1, 2}, map = {1 => 2, 2 => 1, 3 => 2, 4 => 1}
- ...
- bro.size와 map.size가 같아지는 시점에 answer가 증가.
- 결과:
- 총 공평하게 나눌 수 있는 횟수는 2번입니다.
이 코드의 시간 복잡도는 O(n)으로 효율적이며, Map과 Set을 적절히 사용하여 데이터 관리와 비교 연산을 최적화한 점이 특징입니다.
[프로그래머스/JavaScript] Lv.2 롤케이크 자르기
해당 문제는 시간복잡도 O(N)을 개선하는 문제이다. 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘
cocococo.tistory.com
728x90
반응형
'코딩 테스트 준비' 카테고리의 다른 글
[프로그래머스] 뒤에 있는 큰 수 찾기 Lv2 (0) | 2025.01.11 |
---|---|
[프로그래머스] [PCCP 기출문제] 2번 / 퍼즐 게임 챌린지 Lv2 (0) | 2025.01.10 |
[프로그래머스] 귤 고르기 Lv2 (0) | 2025.01.07 |
N과 M (3) 실버 3 (백준, 백트랙킹) (0) | 2023.02.16 |
N과 M (2) 실버 3 (백준, 백트랙킹) (0) | 2023.02.16 |