(此问题与我的previous question相关,或者与my answer相关。)
我想在结构中存储所有自然数的qubes并查找特定的整数以查看它们是否是完美的立方体。
例如,
cubes = map (\x -> x*x*x) [1..]
is_cube n = n == (head $ dropWhile (<n) cubes)
它比计算多维数据集根要快得多,但它的复杂度为O(n^(1/3))
(我是对的吗?)。
我认为,使用更复杂的数据结构会更好。
例如,在C中我可以存储已生成的数组的长度(不是列表 - 用于更快的索引)并进行二进制搜索。 O(log n)
的效率低于another answer 的问题。问题是,我无法在Haskell中表达它(我认为不应该)。
或者我可以使用哈希函数(如mod
)。但我认为拥有多个列表(或列表列表)会占用更多内存,并且不会降低查找(仍为O(n^(1/3))
)的复杂性,只会降低系数。
我想到了一种树,但没有任何聪明的想法(遗憾的是我从未研究过CS)。我认为,所有整数都在上升的事实将使我的树在查找时不平衡。
我很确定这个关于升序整数的事实对于查找来说可能是一个很大的优势,但我不知道如何正确使用它(请参阅我在Haskell中无法表达的第一个解决方案)。
答案 0 :(得分:4)
几条评论:
如果你有多少立方体,请将它们放在Data.IntSet
中。查找是对数时间。算法基于Patricia树和Gill和Okasaki的论文。
如果排序列表中包含无限多个多维数据集,则可以进行二进制搜索。从索引1开始,你会在对数上加倍多次,直到你得到足够大的东西,然后用几个步骤来对数找到你的整数或排除它。但不幸的是,对于列表,每个查找都与索引的大小成比例。并且您不能使用恒定时间查找创建无限数组。
在此背景下,我提出以下数据结构:
排序的多维数据集数组的排序列表。位置
i
的数组包含exp(2,i)
个元素。
然后你有一个稍微复杂的二进制搜索形式。 我不是很清醒,无法从头脑中进行分析,但我相信这会让你得到O((log n)^ 2)最糟糕的情况。
答案 1 :(得分:2)
你可以在懒惰的无限树上进行斐波纳契搜索(或任何其他你喜欢的搜索):
data Tree a = Empty
| Leaf a
| Node a (Tree a) (Tree a)
rollout Empty = []
rollout (Leaf a) = [a]
rollout (Node x a b) = rollout a ++ x : rollout b
cubes = backbone 1 2 where
backbone a b = Node (b*b*b) (sub a b) (backbone (b+1) (a+b))
sub a b | (a+1) == b = Leaf (a*a*a)
sub a b | a == b = Empty
sub a b = subBackbone a (a+1) b
subBackbone a b c | b >= c = sub a c
subBackbone a b c = Node (b*b*b) (sub a b) (subBackbone (b+1) (a+b) c)
is_cube n = go cubes where
go Empty = False
go (Leaf x) = (x == n)
go (Node x a b) = case (compare n x) of
EQ -> True
LT -> go a
GT -> go b