開始進入動態規劃 Leetcode 系列。
理論知識點相關的自行補充,老規則,還是從簡單的題目入手。
Leetcode70
這是道入門級的題目。
求 n 級臺階的總方法數。
到達最後一步 n ,只會有兩種情況,一種是從 n-1(跨了一步),另一種從 n-2 (跨了兩步)上來的。所以,
f(n)=f(n-1)+f(n-2)。
因為每次只能爬 1 階 或者 2 階,所以 f(n) 只能從 f(n-1) 和 f(n-2) 轉移上來,這就意味著 n 階梯總方法數量必然是爬上 n-1 階梯方法數量 + 爬上 n-2 階梯方法數量。
進一步說,你要想知道 n 階方法數,那麼就必須先知道 f(n-1) 方法數 和 f(n-2) 方法數,你要想知道 f(n-1) 方法數,就必須……,
在下面的程式中表現為
res[n]=res[n-1]+res[n-2]
func climbStairs(n int) int {
if n <= 2 {
return n
}
res := make([]int, n+1)
// 如果是一個臺階那麼就只有一種走法
res[1] = 1
// 如果是兩個階就有兩種走法,一種一步一步走兩步,一種直接兩步
res[2] = 2
for i := 3; i <= n; i++ {
res[i] = res[i-1] + res[i-2]
}
return res[n]
}
時間複雜度 O(n)。空間複雜度O(n)。空間複雜度我們可以壓縮成 O(1)。因為我們不需要關心太多之前的資料。
func climbStairs(n int) int {
if n <= 2 {
return n
}
a, b, ret := 1, 1, 0
for i := 2; i <= n; i++ {
ret = a + b
b = a
a = ret
}
return ret
}
Leetcode198
這是一道超高頻的動態規劃面試題,它有一個系列的,今天我們來看它的初始版本。
相鄰的兩家不能偷。如果輸入的只有一家,那麼不用想了,就偷唯一的那戶人家。如果有兩家,那麼偷的必然是兩家中錢多的那家,
那如果總數大於 2 家呢?
對於第 n 家來說,只有兩種選擇偷或者不偷。
如果偷了,那麼當前偷竊總金額=之前 n-2 間房屋偷竊的最高金額+第 n 間房屋金額。
如果不偷,那麼當前偷竊總金額=之前 n-1 間房屋的最高金額。
只要對比這兩個選擇,取最大的值,就是前 n 間房屋能偷到的最多的錢。偽公式如下,
res[n]=max(res[n-1],res[n-2]+nums[n]
func rob(nums []int) int {
if len(nums) == 0 {
return 0
}
if len(nums) == 1 {
return nums[0]
}
res := make([]int, len(nums), len(nums))
res[0] = nums[0]
res[1]=max(res[0],nums[1])
for i := 2; i < len(nums); i++ {
temp := res[i-2] + nums[i]
res[i] = max(temp, res[i-1])
}
return res[len(res)-1]
}
func max(x int, y int) int {
if x > y {
return x
}
return y
}
可以換一種思路,本質上房子有奇數位和偶數位之分。只要在搶奇數位或者偶數位的同時進行比較當前最大值,更新到當前奇數位或者偶數位最高金額即可。
func rob(nums []int) int {
a := 0 // 奇數值
b := 0 //偶數值
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
b = max(a, b+nums[i])
} else {
a = max(b, a+nums[i])
}
}
return max(a, b)
}
func max(x int, y int) int {
if x > y {
return x
}
return y
}
如果文章對你有所幫助,點贊、轉發、留言都是一種支援!
本作品採用《CC 協議》,轉載必須註明作者和本文連結