杨辉三角
思路 一:
找到规则,下一行由上一行的结果决定
输入为 n,则生成 n 行
func generate(numRows int) [][]int {
//创建一个n行的二维数组
var result [][]int
for i := 0; i < numRows; i++ {
var row []int
if i == 0 {
row = append(row, 1)
result = append(result, row)
continue
}
//根据上一行结果生成这一行结果
lastRow := result[i-1]
//这里是<=i,不是<=numRows
//for index := 0; index < numRows; index++ {
for index := 0; index <= i; index++ {
val := getVal(index-1, lastRow) + getVal(index, lastRow)
row = append(row, val)
}
//不要忘了加入到二维数组
result = append(result, row)
}
return result
}
//获取指定下标的值,不存在返回0
func getVal(index int, row []int) int {
if index < 0 || index > len(row)-1 {
return 0
}
return row[index]
}
优化:杨辉三角形每一行是个对称结构,算一半即可
可否直接推出某一行的值
思路二:使用递归迭代,后一行依赖于上一行
思路一:记录所有结果,返回指定行
思路二:只记录上一行的结果,返回指定行
func getRow(rowIndex int) []int {
//注意,这里给的是索引
return generate(rowIndex + 1)[rowIndex]
}
func generate(numRows int) [][]int {
//创建一个n行的二维数组
var result [][]int
for i := 0; i < numRows; i++ {
var row []int
if i == 0 {
row = append(row, 1)
result = append(result, row)
continue
}
//根据上一行结果生成这一行结果
lastRow := result[i-1]
//这里是<=i,不是<=numRows
//for index := 0; index < numRows; index++ {
for index := 0; index <= i; index++ {
val := getVal(index-1, lastRow) + getVal(index, lastRow)
row = append(row, val)
}
//不要忘了加入到二维数组
result = append(result, row)
}
return result
}
//获取指定下标的值,不存在返回0
func getVal(index int, row []int) int {
if index < 0 || index > len(row)-1 {
return 0
}
return row[index]
}
思路三:直接使用计算组合数的公式,利用阶乘
下面的代码会导致整数溢出,
// calculateFactorial 计算阶乘
func calculateFactorial(n int) int64 {
if n == 0 || n == 1 {
return 1
}
var factorial int64 = 1
for i := 2; i <= n; i++ {
factorial *= int64(i)
}
return factorial
}
// combination 使用阶乘定义计算组合数C(n, k)
func combination(n, k int) int {
return (int)(calculateFactorial(n) / (calculateFactorial(k) * calculateFactorial(n-k)))
}
func getRow(rowIndex int) []int {
result := make([]int, rowIndex+1)
for i := 0; i <= rowIndex; i++ {
//注意,这里不能在用append了
//result = append(result, combination(rowIndex, i))
result[i] = combination(rowIndex, i)
}
return result
}
优化:
记录阶乘中间结果,利用对称性质,仍然有溢出问题
// calculateFactorial 计算阶乘
func calculateFactorial(n int) (int64, map[int]int64) {
myMap := map[int]int64{
0: 1,
1: 1,
}
if n == 0 || n == 1 {
return 1, myMap
}
var factorial int64 = 1
for i := 2; i <= n; i++ {
factorial *= int64(i)
myMap[i] = factorial
}
return factorial, myMap
}
// combination 使用阶乘定义计算组合数C(n, k)
func combination(n, k int) int {
nFac, myMap := calculateFactorial(n)
//注意,计算组合数,分母要加括号
//return (int)(nFac / myMap[k] * myMap[n-k])
return (int)(nFac / (myMap[k] * myMap[n-k]))
}
func getRow(rowIndex int) []int {
result := make([]int, rowIndex+1)
for i := 0; i <= rowIndex; i++ {
//注意,这里不能在用append了
//result = append(result, combination(rowIndex, i))
//这里,利用对称的性质进行优化
if i <= rowIndex/2 {
result[i] = combination(rowIndex, i)
} else {
result[i] = result[rowIndex-i]
}
}
return result
}
思路四:利用组合数的递推性质计算
func combination(n, k int) int {
if k == 0 {
return 1
}
//这里还能优化,把中间结果存下来
return combination(n, k-1) * (n - k + 1) / k
}
func getRow(rowIndex int) []int {
result := make([]int, rowIndex+1)
for i := 0; i <= rowIndex; i++ {
//注意,这里不能在用append了
//result = append(result, combination(rowIndex, i))
//这里,利用对称的性质进行优化
if i <= rowIndex/2 {
result[i] = combination(rowIndex, i)
} else {
result[i] = result[rowIndex-i]
}
}
return result
}