빠르게 구현할 수 있고 동시에 모든 요소를 검증할 수 있는 재귀를 사용해 먼저 풀어보았다. 그러나 left와 right의 최대 길이가 각 1000개씩이고, left[0] >= right[0] 일 경우 최대 2개씩 갈라지므로 최대 2의 1000제곱 만큼의 loop 발생한다. 돌려보니 역시나 시간 초과가 발생했다.
constnext = (l, r, sum) => { if (l.length * r.length === 0) { if (sum > max) max = sum; return; }
let lShift = l.slice(1, l.length); let rShift = r.slice(1, r.length);
if (l[0] > r[0]) next(l, rShift, sum + r[0]); else { next(lShift, r, sum); next(lShift, rShift, sum); } };
next(left, right, 0); return max; }
DP로 풀어야 하는 이유
input의 최대 길이가 각 1000이므로 1000을 기준으로 생각해봐야 한다. 2의 1000제곱은 어마어마하게 큰 수지만, 2차원 배열의 크기 1000 x 1000은 백만으로 비교적 다룰만한 수이다. 그리고 2차원 배열의 각 칸에 저장되는 값들도 1~2000 사이 정수들의 합으로 구성되므로 공간복잡도 역시 비교적 작은 편이다.
Top-down vs Bottom-up
6면 모두 단일 숫자로 구성된 주사위가 여러 개 있다. 주사위는 다음과 같은 규칙으로 합쳐버릴 수 있다.
for (let a = 0; a < length + 1; a++) { if (max < getMemo(a, length)) max = getMemo(a, length); if (max < getMemo(length, a)) max = getMemo(length, a); }
for (let a = 0; a < length + 1; a++) { for (let b = 0; b < length + 1; b++) { if ((a === length || b === length) && max < getMemo(a, b)) max = getMemo(a, b); } }