[프로그래머스] 쿠키 구입
문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/49995
접근 방식
몇 개의 바구니를 선택하는지는 상관없다. 몇개를 선택하든지, 총 합이 같기만 하면 된다.
따라서, 투 포인트를 이용해서 구간을 정해서 쿠키의 개수를 세면 되는데
여기서 중요한 점은, 쿠키의 최대 길이가 2천이기에 효율성 테스트에서 시간 초과가 발생할 수 있다는 것이다.
따라서, 효율적으로 문제를 풀어야 한다. 필요할 때마다 양쪽 바구니에 담겨진 쿠키의 개수를 세면 안 되고, 미리 계산을 해 두고 값을 가져와서 사용해야 한다.
바로, 구간 합
을 이용하면 된다.
미리 만들어 둔 sum 배열을 통해, 특정 구간의 합을 구할 수 있다.
예를 들어서, [1, 1, 2, 3]
이라는 배열이 있다면 [0, 1, 2, 4, 7]
이라는 sum 배열을 만든다.
여기서 만약 2번부터 3번 바구니에 담긴 쿠키의 개수를 알고자 한다면,
먼저 3번 바구니까지의 합
을 구하고 (4), 2번 바구니 이전까지의 합
을 빼 주면 된다.
결과적으로는, 3번 바구니까지의 합(4) - 1번바구니까지의 합(1) = 3
임을 알 수 있다.
실제로 1과 2를 합친 3이 답이다.
이를 코드에 녹여내면 된다.
결과
소스 코드
import java.util.*;
class Solution {
public int solution(int[] cookie) {
int answer = 0;
// 구간 합 미리 구하기
int[] sum = new int[cookie.length+1];
for(int i=1; i<=cookie.length; i++){
sum[i] = sum[i-1] + cookie[i-1];
}
// 1번 바구니부터 시작해서 구간을 나누기
for(int start=1; start<=cookie.length; start++){
for(int end=start+1; end<=cookie.length; end++){
int left = start;
int right = end;
// 투포인트를 이용한 구간 합 구하기
while(left<right){
int mid = (left+right) / 2;
int leftSum = sum[mid] - sum[start-1]; // mid까지의 합과 start-1합을 빼기
int rightSum = sum[end] - sum[mid]; // 끝까지의 합과 mid까지의 합을 빼기
// 골고루 나뉘어졌다면, answer 값 갱신하기 while문 종료
if(leftSum==rightSum){
answer = Math.max(answer, leftSum);
break;
}
// 왼쪽합이 더 크다면, 오른쪽 범위 늘리기
else if(leftSum > rightSum){
right = mid;
}
// 오른쪽 합이 더 크다면, 왼쪽의 범위 늘리기
else{
left = mid+1;
}
}
}
}
return answer;
}
}
느낀 점
구간 합과 투포인트를 합쳐서 풀 수 있는 문제였다.
구간 합을 구할 수 있고, 투 포인트를 통해 그 구간을 지정하여 최적의 값을 구하는 알고리즘이다.