動態規劃-走樓梯

題目:有樓梯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))
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章