숫자로 이루어진 배열과 숫자 n을 인수로 받는 함수를 작성해야 한다고 가정해 보겠습니다. 이때 n은 배열의 어떤 요소보다 크거나 같아야 합니다. 이 함수는 배열에서 연속된 요소들의 합이 n을 초과하는 지점마다 배열을 잘라서 여러 개의 하위 배열(subarray)로 분할해야 합니다.
문제 이해하기
예를 들어 다음과 같습니다.
// 원본 배열: const arr = [2, 1, 2, 1, 1, 1, 1, 1]; // 숫자 n이 4일 때 // 기대되는 출력 결과: const output = [ [ 2, 1 ], [ 2, 1, 1 ], [ 1, 1, 1 ] ];
위 예제에서 첫 번째 하위 배열 [2, 1]의 합은 3입니다. 여기에 다음 요소 2를 더하면 5가 되어 n(4)을 초과하므로 새로운 하위 배열이 시작됩니다. 이런 방식으로 전체 배열이 조건에 맞게 분할됩니다.
구현 코드
이 함수는 reduce() 메서드를 활용하면 간결하게 구현할 수 있습니다. 누적값(acc) 안에 현재까지의 합(sum)과 결과 배열(res)을 함께 관리하는 것이 핵심입니다.
const arr = [2, 1, 2, 1, 1, 1, 1, 1];
const splitArray = (arr, num) => {
return arr.reduce((acc, val, ind) => {
let { sum, res } = acc;
// 첫 번째 요소인 경우 새로운 하위 배열 생성
if(ind === 0){
return {sum: val, res:[[val]]};
};
// 현재 합계에 요소를 더해도 num 이하라면 기존 배열에 추가
if(sum + val <= num){
res[res.length-1].push(val);
sum += val;
}else{
// 초과한다면 새로운 하위 배열 시작
res.push([val]);
sum = val;
};
return { sum, res };
}, {
sum: 0,
res: []
}).res;
};
console.log(splitArray(arr, 4));
console.log(splitArray(arr, 5));
코드 동작 방식
- 초기화: reduce의 초기 누적값으로 sum(현재 부분 배열의 합)과 res(결과 배열)를 설정합니다.
- 첫 번째 요소 처리: 인덱스가 0일 경우, 해당 값을 포함한 새로운 하위 배열을 만들고 sum을 초기화합니다.
- 합계 판단: 현재 값(val)을 더했을 때 num 이하라면 마지막 하위 배열에 값을 추가하고, 그렇지 않으면 새로운 하위 배열을 생성합니다.
- 결과 반환: 모든 요소를 순회한 후 최종적으로 res만 반환합니다.
출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[ [ 2, 1 ], [ 2, 1, 1 ], [ 1, 1, 1 ] ] [ [ 2, 1, 2 ], [ 1, 1, 1, 1, 1 ] ]
n이 4일 때와 5일 때 각각 다른 방식으로 배열이 분할되는 것을 확인할 수 있습니다. 이 알고리즘은 배열을 한 번만 순회하므로 시간 복잡도가 O(n)으로 매우 효율적이며, 비용 계산, 페이지네이션, 배치(batch) 처리 등 실무에서도 유용하게 활용할 수 있습니다.