Arrays 查找给定列表中某些元素的所有索引。如果没有Haskell中的数组,它可以在不到O(n^2)的时间内完成吗?

Arrays 查找给定列表中某些元素的所有索引。如果没有Haskell中的数组,它可以在不到O(n^2)的时间内完成吗?,arrays,list,haskell,array-algorithms,Arrays,List,Haskell,Array Algorithms,给定两个唯一、可排序、非连续元素的列表,例如: ['d', 'a', 'z', 'b'] 我想在另一个列表中找到它们的索引,比如: ['a', 'b', 'z', 'd'] 结果将是一份列有其立场的清单: [3, 0, 2, 1] -- element at 0 is at 3, -- element at 1 is at 0, etc. 一个简单的解决方案是使用第二个列表创建Data.Map或哈希表,这样您就可以进行O(logn)索引查找而不是O(n)索引查

给定两个唯一、可排序、非连续元素的列表,例如:

['d', 'a', 'z', 'b']
我想在另一个列表中找到它们的索引,比如:

['a', 'b', 'z', 'd']
结果将是一份列有其立场的清单:

[3, 0, 2, 1]  -- element at 0 is at 3,
              -- element at 1 is at 0, etc.

一个简单的解决方案是使用第二个列表创建Data.Map或哈希表,这样您就可以进行O(logn)索引查找而不是O(n)索引查找。

首先,您必须创建目标数组中所有字符的映射,然后有两个选项:

您可以在
O(n log n)
time中对列表进行排序,如果您要查找的令牌数组长度恒定,您将在
O(log n)
中执行恒定数量的搜索


另一种解决方案是获取目标数组并将其全部放入哈希映射中,然后在那里进行搜索。

这也可以在
O(n log n)
时间内通过几次排序来完成。我假设第二个列表是第一个列表的排列

import Data.List
import Data.Ord
import Data.Function

correspIx :: Ord a => [a] -> [a] -> [(Int, Int)]
correspIx = zip `on` map fst . sortBy (comparing snd) . zip [0..]
correspIx
返回索引相互对应的成对列表:

correspIx "dazb" "abzd" == [(1,0),(3,1),(0,3),(2,2)]
我们需要另一种方法来获得问题中指出的结果:

correspIx' :: Ord a => [a] -> [a] -> [Int]
correspIx' xs ys = map snd $ sortBy (comparing fst) $ correspIx xs ys

现在
correspIx的“dazb”“abzd”==[3,0,2,1]
第二个列表保证是第一个列表的重新排列吗?理论预测,没有数组,函数编程最多慢O(logn)倍。实际上,您可以用具有O(logn)访问权限而不是O(1)访问权限的树映射替换数组。因此,如果你能在命令式世界中发现一个O(f(n))算法,你就知道你能在函数式世界中实现O(f(n)log f(n))。这一差距能否弥合仍然是一个悬而未决的问题。(实际上,许多函数式语言都直接支持数组以避免这个问题)@chi我在哪里可以读到这个理论(或者,我应该在哪个名称下搜索)?@phg我不是这个主题的专家,但似乎是一个很好的开始参考(冈崎在他的书中提到了它,以及Ben Amran&Galil)。@dfeur是的,也许是“一些元素”“这不是最好的措辞。我认为这个答案更实用,因为它不使用哈希表,我相信哈希表使用的是隐藏的数组。@LayGonzález,这取决于你对“哈希表”的解释有多严格。”。在Haskell中,
HashMap
表示为trie。