I have a web app with data in a grid. The user can reorder the columns, and the server can change which columns exist. I would like to save the user\'s column order in a coo
Let's say we have C columns, numbered from 1 to C. We have two sequences sequences of columns, U = u1, u2, ... un and S = s1, s2, ... sm. We want to find a permutation P of S, such that P has no inversions with regard to U and a minimal number of inversions with regard to S.
We can show that there is such an optimal P which is an interleaving of U ∩ S and S \ U. By "interleaving" I mean that P has no inversions with regard to U ∩ S or S \ U.
We can apply dynamic programming to find the optimal interleaving: Let A = (ai) = U ∩ S and B = (bj) = S \ U. Let f(i,j) be the number of inversions w.r.t. S of the optimal interleaving of the prefixes a1...i of A and b1...j of B. The idea is very similar to the longest common subsequence DP algorithm. We have the recurrence
f(0,j) = 0 for all j >= 0
f(i,0) = f(i-1, 0) + sum(k=1 to i-1, [1 if A[i] appears before A[k] in S])
f(i,j) = min(f(i-1, j) + sum(k=1 to i-1, [1 if A[i] appears before A[k] in S])
+ sum(k=1 to j, [1 if A[i] appears before B[k] in S]),
f(i, j-1) + sum(k=1 to i, [1 if B[j] appears before A[k] in S])
+ sum(k=1 to j-1, [1 if B[j] appears before B[k] in S]))
I used the notation [1 if X]
here to denote the value 1
, if X is true and 0
, if X is false.
The matrix f
can be built in time O(|A|^2 * |B|^2). The minimal cost (number of inversions w.r.t. S) will be f(|A|, |B|).
We can reconstruct the optimal permutation using the DP matrix as well: We build it from back to front. We start with the tuple (i,j) = (|A|, |B|) and at every step depending on which of the two options is minimum in the DP transition, we know whether we need to put A[i] or B[j] to the front of the permutation. Then we proceed with (i-1, j) or (i, j-1) depending on which we choose.
Here is an implementation of the algorithm, please excuse my lack of JS skills.