【发布时间】:2014-09-28 20:52:22
【问题描述】:
我们有两个列表xs :: [a] 和ys :: [Int]。例如:
xs = ["some", "random", "text"]
ys = [2, 3, 1]
我们必须生成一个新列表zs :: [a],这样zs 是使用ys 生成的xs 的排列。对于上面的例子:
zs = ["random", "text", "some"]
解释:“random”出现在xs的第二个位置,“text”出现在第三个位置,“some”出现在第一个位置。
到目前为止,我已经得出了这个解决方案:
f :: [a] -> [Int] -> [a]
f xs ys = getList (listArray (1, n) xs) ys where
n = length xs
getList :: Array Int a -> [Int] -> [a]
getList a ys = [ a ! x | x <- ys]
f 是否有更好的定义可以避免使用数组?我正在寻找内存高效的解决方案。如果xs 是一个大字符串列表,那么数组是一个糟糕的选择。 f 的时间复杂度可以放宽到 O(n log n)。
【问题讨论】:
-
Array有什么问题? -
你可以压缩和排序,或者构造一个
Map Int a,但无论哪种方式都会产生一个额外的log(n)因素。 -
假设 n 很大,比如 10^6。我正在寻找一种解决方案,它需要最少的额外内存,但仍保持 O(n) 复杂度。
-
@ChrisMartin:在进行压缩和排序之前,我需要反转 ys stackoverflow.com/q/8322238/1843751
-
我不相信
Array的内存效率低于这里的其他解决方案,因为您没有希望获得真正的“流式传输”解决方案。请注意,即使xs包含大字符串,它们也不会被复制到数组中,而只是对它们的引用。因此,额外的内存开销不一定比构建需要包含 cons 单元的压缩列表之类的东西高。 (我不认为要排序的列表可以融合掉。)
标签: algorithm list haskell permutation