I am studying queuing theory in which I am frequently presented with the following situation.
Let x, y both be n-tuples of nonnegative integers (depicting lengths of the n queues). In addition, x and y each have distinguished queue called their “prime queue”. For example,
x = [3, 6, 1, 9, 5, 2] with x’ = 1
y = [6, 1, 5, 9, 5, 5] with y’ = 5
(In accordance with Python terminology I am counting the queues 0-5.)
How can I implement/construct the following permutation f on {0,1,…,5} efficiently?
- first set f(x’) = y’. So here f(1) = 5.
- then set f(i) = i for any i such that x[i] == y[i]. Clearly there is no need to consider the indices x’ and y’. So here f(3) = 3 (both length 9) and f(4) = 4 (both length 5).
- there are now equally sized sets of queues unpaired in x and in y. So here in x this is {0,2,5} and in y this is {0,1,2}.
- rank these from from 1 to s, where s is the common size of the sets, by length with 1 == lowest rank == shortest queue and s == highest rank == longest queue. So here, s = 3, and in x rank(0) = 1, rank(2) = 3 and rank(5) = 2, and in y rank(0) = 1, rank(1) = 3, rank(2) = 2. If there is a tie, give the queue with the larger index the higher rank.
- pair these s queues off by rank. So here f(0) = 0, f(2) = 1, f(5) = 2.
This should give the permutation [0, 5, 1, 3, 4, 2].
My solution consists of tracking the indices and loops over x and y multiple times, and is terribly inefficient. (Roughly looking at n >= 1,000,000 in my application.)
Any help would be most appreciated.
Since you must do the ranking, you can’t get linear and will need to sort. So it looks pretty straightforward. You do 1. in O(1) and 2. in O(n) by just going over the n-tuples. At the same time, you can construct the copy of x and y with only those that are left for 3. but do not include only the value, but instead use tuple of value and its index in the original.
In your example, x-with-tuples-left would be [[3,0],[1,2],[2,5]] and y-with-tuples-left would be [[6,0],[1,1],[5,2]].
Then just sort both x-with-tuples-left and y-with-tuples-left (it will be O(n.log n)), and read the permutation from the second element of the corresponding tuples.
In your example, sorted x-with-… would be [[1,2],[2,5],[3,0]] and sorted y-with-… would be [[1,1],[5,2],[6,0]]. Now, you nicely see 5. from the second elements: f(2)=1, f(5)=2, f(0)=0.
EDIT: Including O(n+L) in Javascript:
Hopefully it’s correct 😉