List 仅使用列表查找线性时间内列表中不存在的最小非负整数
考虑一个函数List 仅使用列表查找线性时间内列表中不存在的最小非负整数,list,haskell,List,Haskell,考虑一个函数minout::[Int]->Int,它获取一个不同的非负整数列表,并返回列表中不存在的最小非负整数。如果输入有重复项,函数的行为无关紧要。这是否可以在线性时间内实现,只使用列表(没有数组、向量或其他具有有效随机访问的数据结构) (这出现了。)如果l的所有数字都在0和(长度l)-1之间,那么最小值l是长度l,否则,它位于[0..(长度l-1)]。因此minout l始终位于[0..(长度l)],并且只有[0..(长度l-1)]中的l元素相关。我们可以丢弃剩下的元素。利用这一思想,我们
minout::[Int]->Int
,它获取一个不同的非负整数列表,并返回列表中不存在的最小非负整数。如果输入有重复项,函数的行为无关紧要。这是否可以在线性时间内实现,只使用列表(没有数组、向量或其他具有有效随机访问的数据结构)
(这出现了。)如果
l
的所有数字都在0
和(长度l)-1
之间,那么最小值l
是长度l
,否则,它位于[0..(长度l-1)]
。因此minout l
始终位于[0..(长度l)]
,并且只有[0..(长度l-1)]
中的l
元素相关。我们可以丢弃剩下的元素。利用这一思想,我们可以实现线性时间分治解决方案。与合并排序不同,在递归的每个步骤中,我们只递归到两个子列表中的一个子列表中,每个子列表的大小最多为原始列表的一半(在做了一些线性工作之后)。这给出了线性时间复杂度
minout :: [Int] -> Int
minout = minoutaux 0
where
minoutaux :: Int -> [Int] -> Int -- \list base -> smallest integer >= base not occuring in list
minoutaux base [] = base
minoutaux base [x] = base + (if x==base then 1 else 0)
minoutaux base xs = if (length smallpart == n2) then minoutaux (base+n2) bigpart else minoutaux base smallpart
where
n = (length xs)
n2 = n `div` 2
smallpart = [x | x <- xs , base <= x , x < base + n2]
bigpart = [x | x <- xs, base + n2 <= x, x < base + n]
minout::[Int]->Int
minout=minoutaux 0
哪里
minoutaux::Int->[Int]->Int--\list base->最小整数>=列表中未出现基数
米努托碱[]=碱
minoutaux base[x]=base+(如果x==base,则为1,否则为0)
minoutaux base xs=if(长度smallpart==n2),则minoutaux(base+n2)bigpart else minoutaux base smallpart
哪里
n=(长度xs)
n2=n`div`2
smallpart=[x | xRichard Bird在他的书的第一章中描述了这个确切的问题(那一章恰好是亚马逊上的预览版)这是如何在线性时间内运行的?我假设这是在多项式时间内运行的。在每次递归调用期间,整个列表在length
、smallpart
和bigpart
中进行遍历。由于懒惰,在smallpart
和bigpart
中的遍历可能是线性的,但是length
呢?我应该这样做haps之前已经详细解释了这一点。谢谢你指出这一点,我编辑了答案并添加了解释。