为什么在数组中获取值的成本为O(1)

时间:2018-03-20 14:18:32

标签: swift

我理解为什么使用有序索引从数组中获取值是O(1)。但是假设你是按价值获取的?如果值是array.count == 100中的最后一个,则必须遍历整个集合。那不是O(n)吗?

2 个答案:

答案 0 :(得分:1)

简单回答

通过索引在数组中定位值是O(1)。

未排序的数组中搜索值为O(n)。


Big O notation

Array是计算机编程中的抽象数据结构。在讨论抽象数据结构的Big O表示法时,我们要问的是:当给定任意数量的元素时,算法应用于抽象数据结构需要多长时间。换句话说:算法作为抽象结构中数据的函数有多快。


快速上下文

这不是Machine Code。斯威夫特是high-level programming language。含义Swift代码本身就是它运行的计算机内部细节的抽象。因此,当我们在Swift中讨论数组的Big O表示法时,我们并没有真正讨论它是如何存储在内存中的,因为我们假设它存储在内存中的方式是Array data structure的合理表示。我认为理解这一点很重要,这就是为什么Ruby中的数组比C中的数组慢,因为一种语言是运行它的计算机的更大抽象。我们现在可以继续前进,因为知道在Swift数组的上下文中关于Big O的讨论确实受到它在计算机中的底层实现的影响,但是当使用Big O时我们仍然指的是实例化数组的完美版本。


在未排序的数组中搜索值为O(n)

<强> | 2 | 6 | 10 | 0 |

以上文字是包含4个元素的数组的直观表示 如果我每次看一个元素时说,那就是一个复杂度为1的单一动作 然后我说,我希望你只从左到右看一次元素。复杂性有多大?
好的


STOP。

<强> | 2 | 6 | 10 | 0 |

Swift中的

是:

let array: Array<Int> = [2, 6, 10, 0]


  

我希望你只从左到右看一次元素。

我是一名编写Swift的计算机程序员,而你就是计算机。

for element in array {
    print(element)
}

让我们更通用。让我们说我们不知道我们的数组里面有什么,我们把它命名为...... book怎么样。我现在问:我希望你只从左到右看一次元素。复杂性有多大?
嗯,这是书中元素的数量!好。
OK Computer。从左到右查看书中的每个页面,直到页面上有感叹号。如果你找到它,给我看它所在的页面,如果你没找到它,告诉我你没找到它。复杂性有多大? 既然你或我都不知道哪个页面(如果有的话)包含感叹号,那么最后一页完全有可能是唯一包含感叹号的页面。也可能没有页面包含感叹号。

我们图书中的页数是

在最糟糕的情况下,无论我们是否找到感叹号,我们都必须在书中的每一页上至少查看一次,直到我们找到该页面为止

<强> O(n)的


在示例中将所有内容整合在一起

struct Page {
    let content: String
    func contains(_ character: Character) -> Bool {
        return content.contains(character)
    }
    init(_ content: String) {
        self.content = content
    }
}

typealias Book = Array<Page>

let emotionalBook: Book = [Page("this"),
                           Page("is"),
                           Page("a"),
                           Page("simple"),
                           Page("book!")]

let unemotionalBook: Book = [Page("this"),
                             Page("book"),
                             Page("lacks"),
                             Page("emotion.")]

enum EmotionalBook: Error {
    case lacking
}

func findExclamationPoint(within book: Book) throws -> Page {
    //Look at every single page once.
    for page in book {
        if page.contains("!") {
            return page
        }
    }
    //Didn't find a page with ! inside it
    throw EmotionalBook.lacking
}

do {
    //Discovers the last page!
    let emotionalPage = try findExclamationPoint(within: emotionalBook)
    print(emotionalPage.content)
} catch {
    print("This book is \(error) in emotion!")
}

do {
    //Doesn't discover a page, but still checks all of them!
    let emotionalPage = try findExclamationPoint(within: unemotionalBook)
    print(emotionalPage.content)
} catch {
    print("This book is \(error) in emotion!")
}


我希望这有帮助!

答案 1 :(得分:0)

这是我在stackoverflow自我

上找到的最佳答案

array从特定的memory地址start开始。元素占用一定量的字节element_sizearray元素位于memory地址的start中。因此,您可以使用i计算元素start + i * element_size的内存地址。此计算与数组大小无关,因此O(1)。 原来的答案在这里 click me