과자를 바구니 단위로 파는 가게가 있습니다. 이 가게는 1번부터 N번까지 차례로 번호가 붙은 바구니 N개가 일렬로 나열해 놨습니다.
철수는 두 아들에게 줄 과자를 사려합니다. 첫째 아들에게는 l번 바구니부터 m번 바구니까지, 둘째 아들에게는 m+1번 바구니부터 r번 바구니까지를 주려합니다. 단, 두 아들이 받을 과자 수는 같아야 합니다(1 <= l <= m, m+1 <= r <= N). 즉, A[i] 를 i번 바구니에 들어있는 과자 수라고 했을 때, A[l]+..+A[m] = A[m+1]+..+A[r] 를 만족해야 합니다.
각 바구니 안에 들은 과자 수가 차례로 들은 배열 cookie가 주어질 때, 조건에 맞게 과자를 살 경우 한 명의 아들에게 줄 수 있는 가장 많은 과자 수를 return 하는 solution 함수를 완성해주세요. (단, 조건에 맞게 과자를 구매할 수 없다면 0을 return 합니다)
제한사항
조건
위 조건을 만족하는 값 중 최대값을 반환해야 한다. 즉, cookie의 범위 안에 있는 모든 range(l ... r) 에 위 조건을 만족하는 m을 찾고 최대값을 찾으면 된다. 이때 확인해야하는 range의 길이는 2 <= range의 길이 <= cookie.length가 된다. 나는 범위안에 있는 모든 length를, 그리고 해당 length를 만족하는 모든 l 과 r의 값에 대해 조건을 만족하는 m이 있는지 확인했다. m의 값을 찾기위해서는 binary search를 사용했다.
class Solution {
int[] arr;
public int solution(int[] cookie) {
int answer = 0;
// 쿠키의 합계값 저장 (index = 1 부터 시작)
arr = new int[cookie.length + 1];
for (int i = 1; i < arr.length; i++) {
arr[i] = cookie[i - 1] + arr[i - 1];
}
int begin = 1;
int end = arr.length - 1;
int left = 1;
int right = arr.length - 1;
int cnt = 0;
int length = end - begin + 1; //r - l + 1
int maxCnt = cookie.length - length;
// length = range(2 ... cookie.length) 일때 쿠키의 합계 값이 같아지는 mid 가 있다면 answer를 업데이트 해준다
while (length > 1 && left <= right) {
int mid = (right + left) / 2;
int sum1 = sumOfRange(begin, mid); // cookie[begin] + ... + cookie[mid]
int sum2 = sumOfRange(mid + 1, end); // cookie[mid + 1] + ... + cookie[end]
if (sum1 == sum2) {
// answer의 값을 업데이트 해준다
if (answer < sum1) answer = sum1;
//이 range에서 합계가 같은 mid를 찾았으니 다음 range로 넘어간다
left = right + 1;
}
else if (sum1 > sum2) {
right = mid - 1;
}
else {
left = mid + 1;
}
if (left > right) {
cnt++;
if (cnt <= maxCnt) {
begin++;
end++;
left = begin;
right = end;
}
else {
cnt = 0;
length--;
begin = 1;
end = begin + length - 1;
left = begin;
right = end;
maxCnt = cookie.length - length;
}
}
}
return answer;
}
// start 인덱스부터 end 인덱스까지의 쿠키 갯수 리턴 (start & end 포함)
public int sumOfRange(int start, int end) {
return arr[end] - arr[start - 1];
}
}