【发布时间】:2019-11-17 08:35:47
【问题描述】:
给定一个包含负值和正值的数组,我如何找到离中位数最近的第 k 个元素?我有一个快速选择方法,可以找到数组的中位数。然后我遍历原始数组并创建另一个数组diff,其中我保留数组中每个元素的绝对值减去中位数(abs(a[i]-median))。但是,我不知道如何修改我的快速选择和分区来实现这一点。这就是我目前所拥有的。
在数组a的中间找到值:
midpoint=int(len(a)/2)
median=quickSelect(a,0,len(a)-1,midpoint)
quickSelect 看起来像这样:
def quickSelect(array,start,end,k):
if start>=end:
return array[k]
value=partition(array,start,end)
if value>k:
return quickSelect(array,start,value-1,k)
else:
return quickSelect(array,value+1,end,k)
partition 方法如下所示:
def partition(array,start,end):
x=start-1
#pivot is the last element at each iteration
pivot=array[end]
for i in range(start,end):
if array[i]<=pivot:
x+=1
array[x],array[i]=array[i],array[x]
array[x+1],array[end]=array[end],array[x+1]
return x+1
然后我存储差异的绝对值:
diff=[None]*len(a)
for x in range(len(a)):
diff[x]=abs(a[x]-median)
此时我不知道要对用于查找数组中位数的新快速选择和分区函数进行哪些修改。
具有数组[10, 4, 2,15, 18] 和k=2 的示例输出将是4,15
编辑:
我想我已经更接近解决方案了,但是当数组大小更大时,我的新代码会失败。我创建了没有绝对值的数组diff (diff[x]=a[x]-median)
然后我将中间值的位置切换为 0 (diff[midpoint],diff[0]=diff[0],diff[midpoint]),因为没有什么小于中间值的绝对值减去值本身。
然后我创建了一个quickSelectKClosest 函数,该函数调用partitionAbsoluteValue 方法,该方法考虑绝对值。
quickSelectKClosest:
def quickSelectKClosest(array,start,end,k):
if start>=end:
return array[k]
value=partitionAbsoluteValue(array,start,end)
if value>k:
return quickSelectKClosest(array,start,value-1,k)
else:
return quickSelectKClosest(array,value+1,end,k)
partitionAbsoluteValue:
def partitionAbsoluteValue(array,start,end):
x=start-1
pivot=array[end]
for i in range(start,end):
if abs(array[i])<=abs(pivot):
x+=1
array[x],array[i]=array[i],array[x]
array[x+1],array[end]=array[end],array[x+1]
return x+1
然后回到main,我像这样打电话给quickSelectKClosest:
val=quickSelectKClosest(diff,1,len(diff)-1,1+k)
以 1 作为开始,1+k 作为第 k 个值(因为值 0 在 diff[0])
然后我找到quickSelectKClosest返回的值的位置:
indexOfKthLargest=diff.index(val)
最后遍历diff数组,把中间的值加到后面:
for x in range(1,indexOfKthLargest+1):
print(diff[x]+median)
但如果我有一个数组:[16, -23, 53, 19, -39, 99, 84, 95, 7, 6, 64, -79, 89, 43, 41]
和k=3
输出不完全正确:
The median was: 41
The kth closest to the median are
43
53
19
我忘了提这个,但是数组中的值是唯一的,所以它们不会重复。
【问题讨论】:
-
quickSelect(a,0,len(a)-1,midpoint-k)和quickSelect(a,0,len(a)-1,midpoint+k)怎么样? -
你是否受限于 python 2 ?
-
@WalterTross 我不限于 python 2。