我试图想出一个快速算法来计算
数量b[i]= med |y_i+y_j|, 1<=j!=i<=n
何时
y_1,...,y_n
已经排序(因此b[]
是一个向量
长度与y[]
相同。
我将假设y[]
的所有元素都是唯一的
那个n是偶数。
因此,下面的代码计算b[i]
的天真(O(n**2)
)方式:
(为方便起见,我在R中写了这篇文章,但我和语言无关)
n<-30
a_fast<-b_slow<-rep(NA,n)
y<-sort(rnorm(n,100,1))
z<-y
for(i in 1:n){
b_slow[i]<-median(abs(y[-i]+y[i]))
}
我有一个暂定的建议 - 下面 - 在O(n)
中这样做。
但它仅在y[]
包含正数时才有效。
我的问题是:我应该如何更改快速算法
当y[]
包含正面和正面时,也可以工作
负数?这甚至可能吗?
以下(暂定)O(n)
方式下面的代码
(为方便起见,我在R中写了这篇文章,但我和语言无关)
tryA<-floor(1+(n-1)/2+1)
tryB<-floor(1+(n-1)/2)
medA<-y[tryA]
medB<-y[tryB]
for(i in 1:(tryA-1)){
a_fast[i]<-medA+y[i]
}
for(i in tryA:n){
a_fast[i]<-medB+y[i]
}
简单,说明性的例子。如果我们有一个长度为4的向量
-3, -1, 2, 4
然后,例如对于i = 1,3个绝对成对和是
4 1 1
,他们的中位数是1.
然后,例如对于i = 2,3个绝对成对和是
4 1 3
,他们的中位数为3。
这是一个较长的示例,包括正面和负面y[]
:
-1.27 -0.69 -0.56 -0.45 -0.23 0.07 0.13 0.46 1.56 1.72
这里是我的新b_slow[]
(这是地面的投掷,计算了天真的方式):
1.20 0.92 1.00 1.01 0.79 0.53 0.56 0.53 1.33 1.49
但是现在,我的新a_fast[]
不再匹配:
-1.20 -0.62 -0.49 -0.38 -0.16 -0.16 -0.10 0.23 1.33 1.49
这是我对弗朗西斯解决方案的实现(直到我们有两个排序数组,其中位数易于计算)。我在R中做到了这个问题的精神。
尽管如此,我似乎错过了索引的修正因子(下面代码中的ww),因此下面的代码有时会稍微偏离。这是因为在上面的定义中,我们计算了n-1个观测值的中位数(i!= j)。
n<-100
y<-rnorm(n)
y<-sort(y)
b<-rep(NA,n)
#Naive --O(n**2)-- approch:
for(i in 1:n){
b[i]<-median(abs(y[-i]+y[i]))
}
k<-rep(NA,n)
i<-1
k[i]<-min(na.omit(c(which(y+y[i]>0)[1],n))) #binary search: O(log(n)) --
for(i in 2:n){ #O(n)
k_prov<-k[i-1]
while(y[k_prov]+y[i]>0 && k_prov>0) k_prov<-k_prov-1
k[i]<-max(k_prov+1,1)
#for(i in 1:n){ should give the same result.
# k[i]<-which(y+y[i]>0)[1]
#}
}
i<-sample(1:n,1)
x1<--y[1:(k[i]-1)]-y[i]
x2<-y[i]+y[n:k[i]]
x3<-c(x1,x2)
plot(x3)
ww<-ifelse(i<k[i] & i>n/2,n/2+1,n/2)
sort(x3)[ww] #this can be computed efficiently: O(log(n))
b[i] #this is the O(n**2) result.
答案 0 :(得分:4)
这是O(Nxln(N)xln(N))溶液:
所有我:
1)找到项目k,例如j<k <=> y[j]+y[i]<0
(二分法,O(ln(N)))
k分隔两个排序列表:一个在-y [i]之上,另一个在-y [i]之下,应该将符号改为abs(y [i] + y [j])。 现在,我们正在寻找这些列表的中位数。
从这里开始,这只是finding the median of two sorted lists的问题,重复了n次。
2)让我们选择这些列表的最大值(M = abs(y [1] -y [i])或M = abs(y [size] -y [i]))和最小值(m左右)然后重新开始二分法(O(ln(N))。让我们从任何阶段中间选择中间(M + m)/ 2 ...开始,让中间选择......
3)这个大二分法的阶段:第一个列表中有多少项y [j] + y [i]高于(M + m)/ 2?再一次二分法...... O(ln(N))。第二个列表中有多少项-y [j] -y [i]高于(M + m)/ 2?你猜怎么着 ?二分法......总结这两个数字。如果它大于(size-1)/ 2,则m =(M + m)/ 2。否则M =(M + m)/ 2。
4)如果m = M停止! b[i]=m;
我想有人会提供更好的解决方案......
编辑:我应该感谢@ user189035他的O(ln(n + m))算法的链接,以计算两个排序列表的中位数。 How to find the kth smallest element in the union of two sorted arrays?
再见,