Algorithm O(n^2)算法运行时间差
我正试图和哈斯克尔一起解决问题,但我已经超过了时间限制。我很确定我的算法复杂度是我能得到的最好的。因此,我怀疑Haskell本身就是问题所在(库、严格性等),但我不知道它可能是什么Algorithm O(n^2)算法运行时间差,algorithm,haskell,time-complexity,Algorithm,Haskell,Time Complexity,我正试图和哈斯克尔一起解决问题,但我已经超过了时间限制。我很确定我的算法复杂度是我能得到的最好的。因此,我怀疑Haskell本身就是问题所在(库、严格性等),但我不知道它可能是什么 import Data.Array import Data.List main :: IO () main = do x <- readLn interact $ unlines . fmap proccess . take x . lines pro
import Data.Array
import Data.List
main :: IO ()
main = do
x <- readLn
interact $ unlines . fmap proccess . take x . lines
proccess :: String -> String
proccess line = show $ minimumDisjoint line
minimumDisjoint :: String -> Int
minimumDisjoint s = minimumBy sortFn [1..len] -- gets minimum elem from list O(n)
where
len = length s
str = listArray (1, len) s
sortFn i1 i2 = foo i1 i2 -- basically 'string1 > string2' O(n)
where
foo i3 i4
| i3 > len = foo 1 i4
| i4 > len = foo i3 1
| i3 == i1 -1 = ord
| ord == EQ = foo (i3+1) (i4+1)
| otherwise = ord
where
ord = compare (str ! i3) (str ! i4)
导入数据。数组
导入数据。列表
main::IO()
main=do
x字符串
过程行=显示$minimumDisjoint行
最小不相交::字符串->整数
minimumDisjoint s=minimumBy sortFn[1..len]--从列表O(n)中获取最小元素
哪里
len=长度s
str=listArray(1,len)s
sortFn i1 i2=foo i1 i2——基本上是'string1>string2'O(n)
哪里
foo i3 i4
|i3>len=Foo1I4
|i4>len=FooI3 1
|i3==i1-1=ord
|ord==EQ=foo(i3+1)(i4+1)
|否则=ord
哪里
ord=比较(str!i3)(str!i4)
谢谢你的建议 最坏的情况是所有元素都相等的字符串,看起来像
minimumDisjoin
是O(n^2)
也许这会起作用,可能是O(n):
通过字符串查找最小元素的索引列表
但您需要的不是索引连续运行的起始位置和长度的列表:运行长度编码
接下来是处理包裹
然后,在最长距离跑后采取适当的位置
下一关只需比较最长运行设置后的点。最糟糕的情况是,这是原始列表的一半大小,并且正在比较非重叠字符串,比原始重叠问题更有效。由于输入仅为ASCII,您应该尝试使用
ByteString
无处不在,而不是String
,以获得O(1)索引,而不是O(n)在sortFn
和更快的I/O中。我不熟悉Haskel,但您使用的方法是什么,也许您可以简单地解释一下?这个问题可以在O(n)
和O(n*log(n))
时间内解决,两者都应该很容易通过测试。@FordO。如果是O(n^2)
那么问题在于算法,而不是语言非常确定O(n^2)
对于一个长度字符串1e5
已经是1e10
操作的顺序,即使在功能强大的机器上进行了最佳优化C
代码,也只需几秒钟。通常情况下,如果您看到时间限制为0.5s,比如这个问题,你需要努力寻找一个线性或O(n*log(n))
的解决方案,如果你愿意的话,我可以为你提供方法,但是如果最初的主题是询问haskell代码的疑难解答,那么这将是一个离题的问题:Pmuch simpler-将字符串x附加到它本身,x->x+x。现在构建后缀数组,并在其中选择起始索引范围为[0..n-1]的最小后缀