为什么使用队列比使用堆栈(递归调用)慢?

问题描述 投票:0回答:0
import "container/list"

var (
    dr = []int{-1, 1, 0, 0}
    dc = []int{0, 0, -1, 1}
)

func numIslands(grid [][]byte) int {
    cnt := 0

    for i := 0; i < len(grid); i++ {
        for j := 0; j < len(grid[0]); j++ {
            if grid[i][j] == '1' {
                grid[i][j] = '0'
                visit(grid, i, j)
                cnt++
            }
        }
    }
    return cnt
}

func visit(grid [][]byte, r, c int) {
    for i := 0; i < 4; i++ {
        nr := r + dr[i]
        nc := c + dc[i]
        if nr > -1 && nr < len(grid) && nc > -1 && nc < len(grid[0]) && grid[nr][nc] == '1' {
            grid[nr][nc] = '0'
            visit(grid, nr, nc)
        }
    }
}

func numIslands1(grid [][]byte) int {
    cnt := 0
    queue := list.New().Init()

    for i := 0; i < len(grid); i++ {
        for j := 0; j < len(grid[0]); j++ {
            if grid[i][j] == '1' {
                grid[i][j] = '0'
                queue.PushBack([2]int{i, j})
                for queue.Len() != 0 {
                    tmp := queue.Remove(queue.Front()).([2]int)
                    for k := 0; k < 4; k++ {
                        nr := tmp[0] + dr[k]
                        nc := tmp[1] + dc[k]
                        if nr > -1 && nr < len(grid) && nc > -1 && nc < len(grid[0]) && grid[nr][nc] == '1' {
                            grid[nr][nc] = '0'
                            queue.PushBack([2]int{nr, nc})
                        }
                    }
                }
                cnt++
            }
        }
    }
    return cnt
}
func BenchmarkNumIslands(b *testing.B) {
    input := [][]byte{{'1', '1', '0', '0', '0'}, {'1', '1', '0', '0', '0'}, {'0', '0', '1', '0', '0'}, {'0', '0', '0', '1', '1'}}
    output := 3

    b.ResetTimer()
    b.ReportAllocs()
    for i := 0; i < b.N; i++ {
        if result := numIslands(deepCopy(input)); result != output {
            b.Fatalf("expected %d, but got %d", output, result)
        }
    }
}

func BenchmarkNumIslands1(b *testing.B) {
    input := [][]byte{{'1', '1', '0', '0', '0'}, {'1', '1', '0', '0', '0'}, {'0', '0', '1', '0', '0'}, {'0', '0', '0', '1', '1'}}
    output := 3

    b.ResetTimer()
    b.ReportAllocs()
    for i := 0; i < b.N; i++ {
        if result := numIslands1(deepCopy(input)); result != output {
            b.Fatalf("expected %d, but got %d", output, result)
        }
    }
}

func deepCopy(input [][]byte) [][]byte {
    output := make([][]byte, len(input))
    for i := range input {
        output[i] = make([]byte, len(input[i]))
        copy(output[i], input[i])
    }
    return output
}
$ go test -bench=.
goos: windows
goarch: amd64
pkg: my-algo/leetcode/0200.number-of-islands
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkNumIslands-12           5002680               231.9 ns/op           117 B/op          5 allocs/op
BenchmarkNumIslands1-12          1465150               794.2 ns/op           613 B/op         20 allocs/op
PASS
ok      my-algo/leetcode/0200.number-of-islands 4.199s

我解决了200。岛数问题在retcode中有两种方式。

我不明白为什么使用队列比使用堆栈(递归调用)慢。

本来以为这两个函数不会出现太大的区别,因为创建队列中会累积的数据也是在栈内存中分配的,但是和我想的大不相同

基准测试结果还显示内存分配有 4 倍的差异。

不知道那个内存分配到底是什么意思,也不知道为什么相差4倍

看来是很重要的一环,不想错过深渊

如果您能详细解释一下,我将不胜感激

algorithm go depth-first-search breadth-first-search
© www.soinside.com 2019 - 2024. All rights reserved.