LeetCode 77. 组合
题目链接:77. 组合
思路:
Python版本:
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
def backt(path, start):
if len(path)==k:
res.append(path[:])
return
for i in range(start, n+1):
path.append(i)
backt(path, i+1)
path.pop()
res = []
backt([], 1)
return res
go版本:
var res [][]int
func combine(n int, k int) [][]int {
// 不初始化res就会出bug
res = [][]int{}
backt([]int{}, 1, k, n)
return res
}
func backt(path []int, start, k, n int) {
if len(path)==k {
tmp := make([]int, k)
copy(tmp, path)
res = append(res, tmp)
return
}
// 加入剪枝:如果后续所有数字都添加上都不满足len(path)==k时, 则直接结束递归
if len(path)+n-start+1 < k {
return
}
for i:=start; i<=n; i++ {
path = append(path, i)
backt(path, i+1, k, n)
path = path[:len(path)-1]
}
}
关于不初始化res会出现解答错误的问题,具体原因就是LeetCode的判定规则——每道题目你提交之后所用的测试用例共享全局变量,LeetCode提交代码之后是在服务器跑的,多组样例一起传参,但全局变量只会初始化一次,这就是这道题res放在全局变量会出现解答错误的原因(详见此篇博客)。
避免错误有两种办法:一是在combine函数开始位置初始化一下res数组;二是在combine函数开始位置设置一个defer,其实跟初始化一下res数组的思想是一样的,都是避免这个全局变量在运行下一个测试用例的时候还带着上一个用例的数据。
引申:
关于golang语言的切片初始化的问题,运行以下代码进行测试。
package main
import (
"fmt"
)
var res [][]int
func main() {
fmt.Println(res)
fmt.Println(res == nil)
fmt.Println(len(res))
fmt.Printf("%p\n", &res)
}
输出如下:
[]
true
0
0x956450
通过代码运行结果,我们可以得出以下两条结论:
- golang可以对切片赋予默认值,切片的默认值是nil;
- 即使没有进行初始化的切片(被赋予默认值nil的切片),也是拥有一个地址的。