Answers:
对T排序。然后在 T[i] >= i+1
。
例如sorted(T)=[6,4,3,3,1,1]
。然后,T[0] = 6 > 1
,T[1] = 4 > 2
,T[2] = 3 <= 3
最后,T[3] = 3 < 4
所以我们有S = [T[0], T[1], T[2]]
。
从我最初的评论:这是密切相关的学术生产力评估数量无处不在,在赫什指数,更好地被称为 -index。简而言之,它的定义是出版物的数量,每个出版物至少被h引用(最大的h)。
您的问题与众不同的唯一方法是,您不仅会对满足该标准的出版物数量感兴趣,而且会对它们的引文计数是多少感兴趣,但这是一个微不足道的修改。数据已经存在,原始算法只是将其删除。
通常执行的计算非常简单,并且与KarolisJuodelė的回答一致。
更新:根据数据的大小和特征,可能值得探索一些方法,这些方法通过过滤关键点上方和下方的数据对数组进行部分排序(很快就会想到)。然后根据是否太少或太多来调整枢轴并重做包含它的子集,依此类推。您不需要高于元素之间的顺序,当然也不需要那些低于h的元素之间的顺序。因此,举例来说,一旦找到所有大于或等于h 1的元素并且少于h 1,则无需再次触摸该子集,只需对其进行添加即可。这会将快速排序固有的递归转换为尾递归,因此可以将其重写为循环。
我的Haskell有点生锈,但这应该可以完成我上面描述的操作,并且似乎可以正常工作。希望可以一定程度地理解,我很乐意提供进一步的解释。
-- just a utility function
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : merge xs ys
-- the actual implementation
topImpl :: [Int] -> [Int] -> [Int]
topImpl [] granted = granted
topImpl (x:xs) granted
| x == (1 + lGreater + lGranted) = x : merge greater granted
| x > (1 + lGreater + lGranted) = topImpl smaller (x : merge greater granted)
| otherwise = topImpl greater granted
where smaller = [y | y <- xs, y < x]
greater = [y | y <- xs, y >= x]
lGreater = length greater
lGranted = length granted
-- starting point is: top of whole array, granted is empty
top :: [Int] -> [Int]
top arr = topImpl arr []
这个想法是收集granted
您肯定会参与结果的内容,而不是对其进行进一步排序。如果greater
加上x
配合,我们很幸运,否则我们需要尝试用一个较小的子集。(枢轴x
根本不管碰巧,因此目前考虑的子表的第一个项目。)注意,对一个以最大的元素之一显著的优势是,我们做到这一点的平均大小的块,,无需进一步排序。
例:
让我们开始吧[1,3,4,1,3,6]
。
x = 1
,granted = []
,greater = [3,4,1,3,6]
。哎呀,当smaller
第一步的枢轴太小(实际上太小以至于是空的)时,我们遇到了一个病理案例。幸运的是我们的算法已经为此做好了准备。它会丢弃x
并greater
单独尝试。
x = 3
,granted = []
,greater = [4,3,6]
。它们在一起形成一个长度为4的数组,但是我们只能从下面将其限制为3,所以这太多了。greater
独自重复一次。
x = 4
,granted = []
,greater = [6]
。这给出了一个2个元素,每个元素≥4的数组,似乎我们可能会用到更多元素。保持此状态并重复smaller = [3]
。
x = 3
,granted = [4,6]
,greater = []
。这一起给出了3个元素,每个元素≥3的数组,因此我们有了解决方案[3,4,6]
,可以返回。(请注意,置换可根据输入的顺序有所不同,但将始终包含尽可能高的条件,从来没有[3,3,6]
或[3,3,4]
为你的榜样。)
(顺便说一句,递归实际上只是崩溃了一个循环。)由于保存了很多比较,因此复杂度比快速排序好一些:
上面的代码中有一些不必要的比较,例如计算smaller
是否需要我们,可以轻松删除它们。(我认为懒惰的评估会解决这个问题。)
您的算法没有错,当然大多数递归算法都可以转换成循环,这里是您的递归代码的循环版本:
function(T):
while minimum(T) <= lenght(T):
remove minimum(T) from T
loop