题目:有楼梯n阶,从下往上走,每一步只能跨1阶或者2阶,问总共有多少种不同走法
比如,每次走1级台阶,一共走10步。我们可以简写成 1,1,1,1,1,1,1,1,1,1;
再比如,每次走2级台阶,一共走5步。我们可以简写成 2,2,2,2,2。
解答:
—————————————-step.go———————————————
package dynamicprograming // 思路:设f(x)为走到第x阶可能的情况,则最后踏上第n阶的前一步有两种情况,n-1 到 n,或者n-2 到 n,也就是f(n)=f(n-1)+f(n-2) // 又有f(1)=1,f(2)=2 (1+1和2两种情况) // 递归方式,时间复杂度 o(2^n) func f0(n int) int { if n < 1 { return 0 } if n == 1 || n == 2 { return n } return f0(n-1) + f0(n-2) } // 由于f0的递归方式中,计算f(n-1)时,f(1)...f(n-2)都已经计算过了,再次计算f(n-2)...f(1)时会重复计算,因此把这些值保存起来避免重复 // 备忘录递归 时间复杂度 o(n),空间复杂度o(n) func f1(n int, m map[int]int) (ret int) { if n < 1 { return 0 } if n == 1 || n == 2 { return n } ret, exists := m[n] if !exists { ret = f1(n-1, m) + f1(n-2, m) m[n] = ret } return ret } // f1计算时发现,计算f(n)只要知道f(n-2)和f(n-1)即可,n从1遍历到n,会计算所有的f(1)到f(n-1), // 因此依次计算f(1)到f(n-1),并由最后两个值f(n-2),f(n-1)推出f(n)即可 // 动态规划 时间复杂度 o(n),空间复杂度o(1) func f2(n int) int { if n < 1 { return 0 } if n == 1 || n == 2 { return n } a, b, temp := 1, 2, 0 for i := 3; i < n+1; i++ { temp = a + b a = b b = temp } return temp }
————————————–step_test.go————————————————–
package dynamicprograming import ( "testing" "fmt" "time" ) var n=30 func TestF0(t *testing.T) { start:=time.Now().UnixNano() defer func() { fmt.Println("递归耗时",time.Now().UnixNano()-start) }() fmt.Println(f0(n)) } func TestF1(t *testing.T) { start:=time.Now().UnixNano() defer func() { fmt.Println("备忘录递归耗时",time.Now().UnixNano()-start) }() m:=make(map[int]int,n) fmt.Println(f1(n,m)) } func TestF2(t *testing.T) { start:=time.Now().UnixNano() defer func() { fmt.Println("动态规划耗时",time.Now().UnixNano()-start) }() fmt.Println(f2(n)) }