Climbing Stairs
题目描述
爬楼梯:
假设你正在爬楼梯,需要n
级才能到达顶楼。每次可以爬1
或者2
个台阶,有多少种不同的方法爬到楼顶?
示例:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
解法
方法一:递归
时间复杂度:O(2^n)
空间复杂度:O(n)
func climbStairs(n int) int {
if n <= 2 {
return n
}
return climbStairs(n - 1) + climbStairs(n - 2)
}
注意:这种解法时间复杂度太高,效率很差
方法二:递归,保存中间结果
时间复杂度:O(n)
空间复杂度:O(n)
func climbStairs(n int) int {
history := make(map[int]int)
return climbStairsInternally(n, history)
}
func climbStairsInternally(n int, history map[int]int) int{
if v, ok := history[n]; ok {
return v
}
if n <= 2 {
history[n] = n
return n
}
steps := climbStairsInternally(n - 1, history) + climbStairsInternally(n - 2, history)
history[n] = steps
return steps
}
方法三:迭代,也可以称为动态规划
时间复杂度:O(n)
空间复杂度:O(1)
func climbStairs(n int) int {
if n <= 2 {
return n
}
step1 := 1
step2 := 2
result := 0
for n > 2 {
result = step1 + step2
step1, step2 = step2, result
n--
}
return result
}
方法四:斐波那契数列通项公式
该方法当n
很大时,误差也会变大,无法通过leetcode
的执行。
func climbStairs(n int) int {
var nFloat = float64(n)
var xQrt = math.Sqrt(5)
var c1 = math.Pow((1+xQrt)/2, nFloat + 1)
var c2 = math.Pow((1-xQrt)/2, nFloat + 1)
var result = (1 / xQrt) * (c1 - c2)
return int(result)
}
方法五:矩阵快速幂
时间复杂度:
O(logn)
空间复杂度:
O(1)
func climbStairs(n int) int {
matrix := [][]int{
{1, 1},
{1, 0},
}
ans := matrix
temp := matrix
for n > 0 {
if n&1 == 1 {
ans = multiple(ans, temp)
}
temp = multiple(temp, temp)
n = n >> 1
}
return ans[1][0] * 1
}
func multiple(a [][]int, b [][]int) [][]int {
temp := make([][]int, 2)
for i := range temp {
temp[i] = make([]int, 2)
}
for i := 0; i < 2; i++ {
for j := 0; j < 2; j++ {
temp[i][j] = a[i][0]*b[0][j] + a[i][1]*b[1][j]
}
}
return temp
}
Last updated
Was this helpful?