为啥 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)。有人可以解释为啥吗?