I think this can be solved in O(N log(N))
.
Any permutation can be obtained by swapping pairs of adjacent elements; this is why bubble sort works, for example. So let's take a look at the effect of swapping entries (A[i], B[i])
and (A[i+1], B[i+1])
. We want to find out in which cases it's a good idea to make this swap. This has effect only on the i
th and i+1
th terms, all others stay the same. Also, both before and after the swap, both terms have a factor B[1]*B[2]*...*B[i-1]
, which we can call C
for now. C
is a positive number.
Before the swap, the two terms we're dealing with are C*A[i] + C*B[i]*A[i+1]
, and afterwards they are C*A[i+1] + C*B[i+1]*A[i]
. This is an improvement if the difference between the two is positive:
C*(A[i] + B[i]*A[i+1] - A[i+1] - B[i+1]*A[i]) > 0
Since C
is positive, we can ignore that factor and look just at the A
s and B
s. We get
A[i] - B[i+1]*A[i] > A[i+1] - B[i]*A[i+1]
or equivalently
(1 - B[i+1])*A[i] > (1 - B[i])*A[i+1]
Both of these expressions are nonnegative; if one of B[i]
or B[i+1]
is one, then the term containing 'one minus that variable' is zero (so we should swap if B[i]
is one but not if B[i+1]
is one); if both variables are one, then both terms are zero. Let's assume for now that neither is equal to one; then we can rewrite further to obtain
A[i]/(1 - B[i]) > A[i+1]/(1 - B[i+1])
So we should compute this expression D[i] := A[i]/(1 - B[i])
for both terms and swap them if the left one is greater than the right one. We can extend this to the case where one or both B
s are one by defining D[i]
to be infinitely big in that case.
OK, let's recap - what have we found? If there is a pair i
, i+1
where D[i] > D[i+1]
, we should swap those two entries. That means that the only case where we cannot improve the result by swapping, is when we have reordered the pairs so that the D[i]
values are in increasing order -- that is, all the cases with B[i] = 1
come last (recall that that corresponds to D[i]
being infinitely large) and otherwise in increasing order of D[i]
value. We can achieve that by sorting with respect to the D[i]
value. A quick examination of our steps above shows that the order of pairs with equal D[i]
value does not impact the final value.
Computing all D[i]
values can be done in a single, linear-time pass. Sorting can be done with an O(N log(N))
algorithm (we needed the swapping-of-neighbouring-elements stuff only as an argument/proof to show that this is the optimal solution, not as part of the implementation).