我有一个已经按降序排序的整数列表,但是一个函数接受第一个元素的值(让我们称之为x
)并将subtract 1
映射到{{ 1}}应用列表其余部分的值(不包括第一个元素)。 (我正在尝试实现递归算法来检查a graphic sequence。)
x
新列表需要按递减顺序再次排序,以便进行下一步递归。我尝试过使用list1 = [4,4,3,2,2,2,2,1] --an example of a nonincreasing list
newList = (/s -> map (subtract 1) (fst s) ++ snd s) $ splitAt (head list1) (tail list1)
--newList == [3,2,1,1,2,2,1]
--only these four need to be swapped | | | |
sortedList = sortFunction newList --[3,2,2,2,1,1,1]
,但对于大型列表来说这变得相当慢,因为它适用于每个级别的递归。
将Data.List.sort
映射到非增量整数列表开头的性质意味着在反转的位置实际上只有一个点:例如,在前面的代码中,前两个{{1只需要与下两个subtract 1
进行交换,以便对列表进行排序。
进行此排序的最有效(即最快)方法是什么?此外,是否有更高效的数据结构可用于代替此工作的列表?
答案 0 :(得分:3)
你可能最好做一些游程编码。然后你不必深入挖掘以保持列表的排序。
(警告:未经测试的Haskell代码。)函数
std::vector<int>
将rlEncode xs = [(length xs', head xs') | xs' <- reverse $ group $ sort xs]
变为[4,4,3,2,2,2,2,1]
。然后我们可以写一个“构造函数”
[(2,4),(1,3),(4,2),(1,1)]
和“析构函数”
rlCons (n, x) [] = [(n, x)]
rlCons (n, x) rle@((n', x') : rle')
| x == x' = (n + n', x) : rle'
| otherwise = (n, x) : rle
用于游程编码列表。然后rlUncons [] = Nothing
rlUncons ((1, x) : rle) = Just (x, rle)
rlUncons ((n, x) : rle) = Just (x, (n - 1, x) : rle)
以最简单,效率最低的形式显示如下。
isGraphic