This question was asked to me in an interview, and I was unable to come up with an optimal solution.
Given an even size array, we can perform any operation on the array, until the array becomes empty such that the overall cost should be minimum.
Operations:
- remove first and last element => cost will be gcd(first, last)
- remove first and middle element => cost will be gcd(first, middle)
- remove middle and last element => cost will be gcd(middle, last)
Note:
Example:
Input: [2, 4, 8, 6]
Output: 4
Explanation:
Regardless of the order we perform the operations, the state of the list can be described with four pointers that describe exactly the two remaining, contiguous sections of the list.
These pointers are related by a specific set of rules that restrict which states are possible to achieve. I would start with using the four pointer combination and conduct recursion with memoised state.
We can reduce the state further by observing that the two contiguous sections can differ in length by either 0 or 2. I'll try to update this answer later.
JavaScript code (random test in Python against brute force available here):
function gcd(x, y){
while(y)
[x, y] = [y, x % y];
return x;
}
function f(A){
const memo = {};
const n = A.length;
const mid = n / 2;
function g(l0, l1, r0, r1){
const key = String([l0, l1, r0, r1]);
if (memo.hasOwnProperty(key))
return memo[key];
const len_l = l1 - l0 + 1;
const len_r = r1 - r0 + 1;
if (len_l + len_r == 2){
if (len_r && len_l)
return gcd(A[l0], A[r0]);
else if (len_l)
return gcd(A[l0], A[l0 + 1]);
else
return gcd(A[r0], A[r0 + 1]);
}
let a = A[l0];
let b = A[r1];
const outer = gcd(a, b) + g(l0 + 1, l1, r0, r1 - 1);
if (len_r >= len_l)
var mid = r0 + (len_l + len_r) / 2 - len_l;
else
var mid = l0 + (len_l + len_r) / 2;
b = A[mid];
const _l1 = l1 - (mid == l1 ? 1 : 0);
const _r0 = r0 + (mid == r0 ? 1 : 0);
const left = gcd(a, b) + g(l0 + 1, _l1, _r0, r1);
a = A[r1];
const right = gcd(b, a) + g(l0, _l1, _r0, r1 - 1);
return memo[key] = Math.min(outer, left, right);
}
return g(0, mid - 1, mid, n - 1);
}
let A = [2, 4, 8, 6];
console.log(JSON.stringify(A));
console.log(f(A));
A = [8,5,21,10,25,9]
console.log(JSON.stringify(A));
console.log(f(A));
const n = 200;
A = [];
for (let i=0; i<n; i++)
A.push(i + 1);
console.log(JSON.stringify(A));
console.log(f(A));