函数,它在整数列表中找到下标的最长有序增量之一(不一定是连续的)数字。例如:
•序列[21,27,15,14,18,16,14,17,22,13]
= [14,16,17,22]
我的函数有一个问题,它从数组中获取初始数,并查找序列:
fstLen:: Int -> [Int] -> [Int]
fstLen a [] = a: []
fstLen x (l:ls) = if x < l then x:(fstLen l ls) else fstLen x ls
我遇到了问题,14,18,16,14,17,22,13 14&lt; 18然后18> 16,我的算法以数字16为基础,正在寻找新的序列,我需要回到14 我该怎么办?
(对不起我的英文)
答案 0 :(得分:3)
您可以随时使用subsequences
中的Data.List
来获取列表中所有可能的子序列。当您获得这些子序列时,只需使用此函数和filter
:
isSorted :: (Ord a) => [a] -> Bool
isSorted [] = True
isSorted [_] = True
isSorted(x:y:xs) = x <= y && isSorted (y:xs)
然后使用maximumBy
(或其他方法)获取最大长度子序列,排序为comparing
length
。
这是代码的样子:
import Data.Ord (comparing)
import Data.List (subsequences, maximumBy, nub)
isSorted :: (Ord a) => [a] -> Bool
isSorted [] = True
isSorted [_] = True
isSorted(x:y:xs) = x <= y && isSorted (y:xs)
max_sequence :: (Ord a) => [a] -> [a]
max_sequence xs = maximumBy (comparing length) $ map nub $ filter isSorted (subsequences xs)
这似乎工作正常:
*Main> max_sequence [21,27,15,14,18,16,14,17,22,13]
[14,16,17,22]
注意:使用map nub
从子序列中删除重复的元素。如果没有使用,那么这将返回[14,14,17,22]
作为最大子序列,如果允许,这可能没问题。
答案 1 :(得分:3)
通过维护地图
,可以实现更高效的n log n
解决方案
并且地图保持对于递增序列的每个可能大小的不变性,仅保留按字典顺序排列的最大序列。
额外traceShow
以显示从列表末尾折叠时地图如何变化:
import Debug.Trace (traceShow)
import Data.Map (empty, elems, insert, delete, lookupGT, lookupLT)
-- longest (strictly) increasing sequence
lis :: (Ord k, Show k, Foldable t) => t k -> [k]
lis = snd . maximum . elems . foldr go empty
where
go x m = traceShow m $ case x `lookupLT` m of
Nothing -> m'
Just (k, v) -> if fst a < fst v then m' else k `delete` m'
where
a = case x `lookupGT` m of
Nothing -> (1, [x])
Just (_, (i, r)) -> (i + 1, x:r)
m' = insert x a m
然后:
\> lis [21,27,15,14,18,16,14,17,22,13]
fromList []
fromList [(13,(1,[13]))]
fromList [(22,(1,[22]))]
fromList [(17,(2,[17,22])),(22,(1,[22]))]
fromList [(14,(3,[14,17,22])),(17,(2,[17,22])),(22,(1,[22]))]
fromList [(16,(3,[16,17,22])),(17,(2,[17,22])),(22,(1,[22]))]
fromList [(16,(3,[16,17,22])),(18,(2,[18,22])),(22,(1,[22]))]
fromList [(14,(4,[14,16,17,22])),(16,(3,[16,17,22])),(18,(2,[18,22])),(22,(1,[22]))]
fromList [(15,(4,[15,16,17,22])),(16,(3,[16,17,22])),(18,(2,[18,22])),(22,(1,[22]))]
fromList [(15,(4,[15,16,17,22])),(16,(3,[16,17,22])),(18,(2,[18,22])),(27,(1,[27]))]
[15,16,17,22]
没有必要在地图中保留列表。可以仅使用密钥和序列的长度(即,仅元组的第一元素)来重建最长的增加序列。