Go每週刷題第四周

Remember發表於2021-01-31

開始進入動態規劃 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 協議》,轉載必須註明作者和本文連結
吳親庫裡