为啥 O(n^2) 解决方案更快? 2020 年代码出现的第 1 天

Posted

技术标签:

【中文标题】为啥 O(n^2) 解决方案更快? 2020 年代码出现的第 1 天【英文标题】:Why is the O(n^2) solution faster? Day 1 Advent of Code 2020为什么 O(n^2) 解决方案更快? 2020 年代码出现的第 1 天 【发布时间】:2021-10-25 00:37:43 【问题描述】:

对于 Advent of Code 中的第一个问题,我有两个解决方案。第一个解决方案 (p1) 的时间复杂度为 O(n)。 O(n^2) 的第二个 (p2)。但是为什么第二个更快呢?

https://adventofcode.com/2020/day/1

基准P1 12684 92239 ns/op BenchmarkP2 3161 90705 ns/op

//O(n)
func p1(value int) (int, int)

    m := make(map[int]int)

    f, err := os.Open("nums.txt")
    printError(err)
    defer f.Close()
    scanner := bufio.NewScanner(f)

    for scanner.Scan() 
        intVar, err := strconv.Atoi(scanner.Text())
        printError(err)
        m[intVar]=intVar
    

    for _, key := range m 
        l, ok := m[value-key]
        if ok 
            return l, key
        
    
    return 0, 0


//O(n^2)
func p2(value int) (int, int)

    var data []int

    f, err := os.Open("nums.txt")
    printError(err)
    defer f.Close()
    scanner := bufio.NewScanner(f)

    for scanner.Scan() 
        intVar, err := strconv.Atoi(scanner.Text())
        printError(err)
        data= append(data, intVar)
    

    for ki, i := range data 
        for kj, j := range data 
            if ki != kj && i+j == value 
                return i , j
            
        
    
    return 0, 0

【问题讨论】:

代码中n对应什么? 输入有多大?对于小输入,O(n2) 可能比 O(n) 快。 Big-O 表示法只描述了渐近复杂度(即当 n 很大时)。 @mkrieger1 到搜索循环。对于这两个函数,最后一个循环 @jub0bs 我已经用 200 个值和 400 个值对其进行了测试 @jub0bs 啊,在 800 它交换。我认为 200 个值就足够了,但显然不是。谢谢 【参考方案1】:

只需尝试更多测试数据

func main() 
    // generate txt
    generateTxt(10000)
    // test
    time := countTime(p1)
    fmt.Println("time cost of O(n^2): ", time)
    time = countTime(p2)
    fmt.Println("time cost of O(n): ", time)


func countTime(f func(int) (int, int)) int64 
    tick := time.Now().UnixNano()
    fmt.Println(tick)
    f(2020)
    tock := time.Now().UnixNano()
    return tock - tick

结果(ns):

data O(n) O(n^2)
500 510700 529900
5000 787900 4589600

解释

Big-O是指时间成本随着数据规模的增加而增加,所以小数据不能很好地反映这一点。

还要注意:p1 需要花费一些时间来制作地图。如果你在 p1 之后尝试 p2,p2 的 io 也可能从缓存中受益。

【讨论】:

以上是关于为啥 O(n^2) 解决方案更快? 2020 年代码出现的第 1 天的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 O(NLogN) 算法查找字谜比我的 O(N) 算法运行得更快?

预期时间复杂度为 O(n^2),但结果为 O(n)。有人可以解释为啥吗?

位运算符更快吗?如果是,那为啥?

为啥以下算法(循环排序?!)的时间复杂度是 O(n)?

为啥在 Node.js 中阻塞文件 I/O 时异步性能更差?

算法-排序