我正在研究排队论,我经常会遇到以下情况。
设x,y都是非负整数的n元组(描述n个队列的长度)。另外,x和y各自具有称为“主要队列”的区别队列。例如,
x = [3,6,1,9,5,2],x'= 1
y = [6,1,5,9,5,5],y'= 5
(根据Python术语,我计算队列0-5。)
如何有效地在{0,1,...,5}上实现/构造以下排列f?
这应该给出排列[0,5,1,3,4,2]。
我的解决方案包括多次跟踪x和y上的索引和循环,并且非常低效。 (在我的申请中粗略地看n> = 1,000,000。)
非常感谢任何帮助。
答案 0 :(得分:1)
由于您必须进行排名,因此无法获得线性并且需要排序。所以它看起来非常简单。你只需要遍历n元组就可以在O(1)和O(n)中做1.同时,您可以构造x和y的副本,只包含那些留给3的那些副本但不包含该值,而是使用值的元组及其原始索引。
在你的例子中,x-with-tuples-left将是[[3,0],[1,2],[2,5]]和y-with-tuples-left将是[[6,0] ],[1,1],[5,2]。
然后只排序x-with-tuples-left和y-with-tuples-left(它将是O(n.log n)),并从相应元组的第二个元素中读取排列。
在你的例子中,排序x-with -...将是[[1,2],[2,5],[3,0]]并且y-with -...排序为[[1] ,1],[5,2],[6,0]。现在,你很好地从第二个元素看到5. f(2)= 1,f(5)= 2,f(0)= 0。
编辑:在Javascript中包含O(n + L):
function qperm (x, y, xprime, yprime) {
var i;
var n = x.length;
var qperm = new Array(n);
var countsx = [], countsy = []; // same as new Array()
qperm[xprime] = yprime; // doing 1.
for (i = 0; i < n; ++i) {
if (x[i] == y[i] && i != xprime && i != yprime) { // doing 2.
qperm[i] = i; }
else { // preparing for 4. below
if (i != xprime) {
if (countsx[x[i]]) countsx[x[i]]++; else countsx[x[i]] = 1; }
if (i != yprime) {
if (countsy[y[i]]) countsy[y[i]]++; else countsy[y[i]] = 1; } }
// finishing countsx and countsy
var count, sum;
for (i = 0, count = 0; i < countsx.length; ++i) {
if (countsx[i]) {
sum = count + countsx[i];
countsx[i] = count;
count = sum; }
for (i = 0, count = 0; i < countsy.length; ++i) {
if (countsy[i]) {
sum = count + countsy[i];
countsy[i] = count;
count = sum; }
var yranked = new Array(count);
for (i = 0; i < n; ++i) {
if (i != yprime && (x[i] != y[i] || i == xprime)) { // doing 4. for y
yranked[countsy[y[i]]] = y[i];
countsy[y[i]]++; } }
for (i = 0; i < n; ++i) {
if (i != xprime && (x[i] != y[i] || i == yprime)) { // doing 4. for x and 5. at the same time
// this was here but was not right: qperm[x[i]] = yranked[countsx[x[i]]];
qperm[i] = yranked[countsx[x[i]]];
// this was here but was not right: countsy[y[i]]++; } } }
countsx[x[i]]++; } }
return qperm; }
希望这是正确的; - )