简体   繁体   English

我如何在 haskell 中进行检查 O(1),而不是 O(n)?

[英]How can i make my check O(1), not O(n) in haskell?

get1 [] n = error "List is too small"
get1 xs n|n<0 = error "Use positive numbers"          
get1 (x:xs) 0 = x
get1 (x:xs) n = get1 xs (n-1)

I have get function made myself, but my check for positive numbers goes for O(n).我得到了 function 自己做的,但我对正数的检查是 O(n)。 What should i do to make this O(1)?我应该怎么做才能使这个 O(1)? I'm new in haskell, so recommend me something simple, please我是 haskell 的新手,所以请给我推荐一些简单的东西

If you stay with linked lists, you cannot do better than O(n).如果你坚持使用链表,你不会比 O(n) 做得更好。 So if you want better, you'll have to use a different data structure;因此,如果您想要更好,则必须使用不同的数据结构; for O(1) essentially your only choice is an array, though there are many options if you allow yourself to relax to O(log n).对于 O(1),基本上你唯一的选择是一个数组,但如果你让自己放松到 O(log n),还有很多选择。 And remember, for all n, log n < 30.请记住,对于所有 n,log n < 30。

[Int] is a linked list type. [Int]是一个链表类型。 Using this data structure, there's no faster way to access the Nth element than traveling through the first N ones.使用这种数据结构,没有比遍历前 N 个元素更快的方法来访问第 N 个元素。

In the case you are using get1 in another function f and you find that to be too slow, you either need to switch to a new data structure or (very commonly) rewrite f to avoid get1 .如果您在另一个 function f中使用get1并且您发现速度太慢,您要么需要切换到新的数据结构,要么(非常常见)重写f以避免get1 For instance, this is a common beginner mistake:例如,这是一个常见的初学者错误:

-- add 10 to each element in the list
add10 :: [Int] -> [Int]
add10 xs = [ 10 + get1 xs i | i <- [0 .. length xs-1] ]

This function "works" but is rather inefficient.这个 function “有效”,但效率相当低。 For a list of length N, we pay O(N) for each get1 , and we make O(N) such calls, for a total of O(N^2) where, intuitively, O(N) would suffice.对于长度为 N 的列表,我们为每个get1支付 O(N) 费用,并且我们进行 O(N) 次这样的调用,总共需要 O(N^2) ,从直觉上讲,O(N) 就足够了。

The solution, in this case, is to avoid working with indices i but directly scan the list.在这种情况下,解决方案是避免使用索引i而是直接扫描列表。

-- add 10 to each element in the list
add10 :: [Int] -> [Int]
add10 xs = [ 10 + x | x <- xs ]

In some other languages, to scan a list/array/sequence we need to work with indices.在其他一些语言中,要扫描列表/数组/序列,我们需要使用索引。 In Haskell, that's not the proper way to do it.在 Haskell 中,这不是正确的方法。

As a thumb rule, if you are a beginner and start working with lists, you should avoid functions like length, !!作为经验法则,如果您是初学者并开始使用列表,则应避免使用length, !! in most cases.在大多数情况下。 I'd also recommend to avoid partial functions like head, tail .我还建议避免使用head, tail等部分功能。 In general, many problems can be efficiently solved with lists using recursion and pattern matching, folds, maps, zip / zipWith , list comprehensions, and the like.通常,使用递归和模式匹配、折叠、映射、 zip / zipWith 、列表推导等可以有效地解决许多问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM