[英]What's the most efficient way to sort an array with a single series of inversions?
I have a list of integers that has already been sorted in a descending order, but a function that takes the value of the first element (let's call that x
) and maps subtract 1
to x
values of the rest of the list (excluding the first element) is applied. 我有一个已经按降序排序的整数列表,但是有一个函数接收第一个元素的值(让我们称
x
),然后将subtract 1
映射到列表中其余部分的x
值(不包括第一个)元素)。 (I am trying to implement the recursive algorithm to check for a graphic sequence .) (我正在尝试实现递归算法来检查图形序列 。)
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]
The new list needs to be sorted again in a descending order for the next step of recursion. 新列表需要按降序再次排序,以进行下一步递归。 I've tried using
Data.List.sort
, but this becomes fairly slow for large lists, as it is applied for every level of recursion. 我尝试使用
Data.List.sort
,但是对于大型列表,这变得相当慢,因为它适用于每个递归级别。
The nature of mapping subtract 1
to the beginning of a list of nonincreasing integers means that there is really only one spot at where there is an inversion: for example, in the previous code, the first two 1
's only need to be exchanged with the next two 2
's in order to sort the list. 将
subtract 1
映射到非递增整数列表的开头的性质意味着实际上只有一个点存在反转:例如,在前面的代码中,只需要与前两个1
交换即可。接下来的两个2
以对列表进行排序。
What's the most efficient (ie fastest) way to do this sorting? 什么是最有效(即最快)的分类方法? Also, is there a more efficient data structure to use instead of lists for this job?
此外,是否有更有效的数据结构可用于代替此工作的列表?
You might be better off doing run-length encoding. 您最好进行游程长度编码。 Then you don't have to dig very far to keep the list sorted.
这样,您就不必进行太多挖掘就可以对列表进行排序。
(WARNING: untested Haskell code.) A function (警告:未经测试的Haskell代码。)一个函数
rlEncode xs = [(length xs', head xs') | xs' <- reverse $ group $ sort xs]
turns [4,4,3,2,2,2,2,1]
into [(2,4),(1,3),(4,2),(1,1)]
. 将
[4,4,3,2,2,2,2,1]
变成[(2,4),(1,3),(4,2),(1,1)]
。 Then we can write a "constructor" 然后我们可以写一个“构造函数”
rlCons (n, x) [] = [(n, x)]
rlCons (n, x) rle@((n', x') : rle')
| x == x' = (n + n', x) : rle'
| otherwise = (n, x) : rle
and a "destructor" 和一个“破坏者”
rlUncons [] = Nothing
rlUncons ((1, x) : rle) = Just (x, rle)
rlUncons ((n, x) : rle) = Just (x, (n - 1, x) : rle)
for run-length encoded lists. 用于行程编码列表。 Then
isGraphic
, in its simplest and least efficient form, looks like this. 然后,
isGraphic
以其最简单,最不高效的形式显示如下。
isGraphic [] = True
isGraphic rle = fromMaybe False $ do
(d, rle') <- rlUncons rle
rle'' <- deflate d rle'
return $ isGraphic rle''
deflate 0 rle = Just rle
deflate _d [] = Nothing
deflate _d [(_,0)] = Nothing
deflate d ((n, d') : rle)
| d < n = Just $ rlCons (n - d, d') $ rlCons (d, d' - 1) rle
| otherwise = liftM (rlCons (n, d' - 1)) $ deflate (d - n) rle
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.