Golang递归实现汉诺塔问题时遇到slice越界错误该如何解决
Golang递归实现汉诺塔问题时遇到slice越界错误该如何解决
package main
import (
"fmt"
)
func move(n int, source, target, auxiliary []int) {
if n > 0 {
move(n-1, source, auxiliary, target)
curr := source[len(source)-1]
target = append(target, curr)
source = source[:len(source)-1]
fmt.Printf("%v\n%v\n%v\n", source, auxiliary, target)
move(n-1, auxiliary, target, source)
}
}
func main() {
var (
a = []int{3, 2, 1}
b = []int{}
c = []int{}
)
move(3, a, c, b)
}
更多关于Golang递归实现汉诺塔问题时遇到slice越界错误该如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html
6 回复
你尝试过使用像 delve 这样的调试器吗?
更多关于Golang递归实现汉诺塔问题时遇到slice越界错误该如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我使用了VS Code自带的调试器。我遇到的问题是在递归调用过程中,名为source的切片长度不知为何变成了小于0的值。
你使用调试器时找到原因了吗?
如果没有,也许可以尝试在纸上逐步推演你的算法:写下每一步后每个变量的状态,并仔细思考为什么变量会以这种方式被改变。
请记住:算法的正确性与实现它的编程语言无关。
不,我找不到原因。
我已经用Python和Kotlin实现了相同的算法。在这些语言中,它运行得很好。
我是Go编程的新手。我推测,在我从源切片中移除最后一个元素后,其长度的变化并没有在递归调用之间传递。这个问题是否可能是因为切片是引用类型而导致的?
这是一个典型的Go语言slice引用问题。你的代码中slice作为参数传递时,对slice的修改不会反映到原始slice上,导致递归过程中slice状态不一致。
问题在于:
append返回的是新slice,需要赋值回原变量- slice作为参数传递时,函数内部修改不会影响调用方的slice
以下是修正后的代码:
package main
import (
"fmt"
)
func move(n int, source, target, auxiliary *[]int) {
if n > 0 {
move(n-1, source, auxiliary, target)
// 从源柱子取出最上面的盘子
curr := (*source)[len(*source)-1]
*source = (*source)[:len(*source)-1]
// 将盘子放到目标柱子
*target = append(*target, curr)
fmt.Printf("A: %v\nB: %v\nC: %v\n\n", *source, *auxiliary, *target)
move(n-1, auxiliary, target, source)
}
}
func main() {
var (
a = []int{3, 2, 1}
b = []int{}
c = []int{}
)
move(3, &a, &c, &b)
}
或者使用返回值的方式:
package main
import (
"fmt"
)
func move(n int, source, target, auxiliary []int) ([]int, []int, []int) {
if n > 0 {
source, auxiliary, target = move(n-1, source, auxiliary, target)
// 移动盘子
curr := source[len(source)-1]
source = source[:len(source)-1]
target = append(target, curr)
fmt.Printf("A: %v\nB: %v\nC: %v\n\n", source, auxiliary, target)
auxiliary, target, source = move(n-1, auxiliary, target, source)
}
return source, target, auxiliary
}
func main() {
var (
a = []int{3, 2, 1}
b = []int{}
c = []int{}
)
move(3, a, c, b)
}
关键修改:
- 使用指针传递slice,确保递归调用中能修改原始slice
- 或者通过返回值传递修改后的slice状态
- 确保每次移动后slice的长度变化能正确传递到递归的下一层

