2020.04.11
這題其實正常思路還可以,有點類似b站李永樂老師講的方法。
核心還是尋找子問題,dp[i][j]
表示一共有i層j個雞蛋。可以把dp[i][j]
分為先在第m層扔一次,在剩下的結果裡繼續分析。dp[i][j] = min(dp[i][j], max(dp[m][j-1], dp[n-m][j]))
第乙個min
對應最優解,第二個max
表示最差的情況。
這麼分析的話複雜度為o(k
n2)o(kn^2)
o(kn2)
仔細觀察其實選擇第一次扔的樓層這一問題也是可以優化的,我們希望得到乙個最佳的第一次扔樓層。想一下,從頂層扔和從底層扔其實一樣,都剩下n-1的樓層需要去進一步驗證。我們希望得到的是第一次扔完以後最壞情況和最好情況的最接近。此時最壞情況是最下的。
class
solution
(object):
defsupereggdrop
(self, k, n)
:"""
:type k: int
:type n: int
:rtype: int
"""dp =[[
float
('inf')]
*(k+1)
for _ in
range
(n+1)]
# [n][k] 樓層最低0,雞蛋最少1
for i in
range
(k+1):
# 第1層,無論多少雞蛋都扔一次(0) 第0層不用扔
dp[1]
[i]=
1 dp[0]
[i]=
0for i in
range
(n+1):
# 只有1個雞蛋有幾層扔幾次
dp[i][0
]= i
dp[i][1
]= i
for i in
range(2
, k+1)
:# 蛋
for j in
range(2
,n+1):
## 層
left =
1 right = j
while left<=right:
k =(right+left)
>>
1 broken = dp[k-1]
[i-1
]
notbroken = dp[j-k]
[i]if notbroken>broken:
left = k+
1elif notbroken
right = k-
1else
:break
dp[j]
[i]=
max(broken,notbroken)+1
return dp[-1
][-1
]
作為對比我貼上自上而下的帶有備忘錄的方法。
class
solution
:def
supereggdrop
(self, k:
int, n:
int)
->
int:
memo =
defdp
(k, n):if
(k, n)
notin memo:
if n ==0:
ans =
0elif k ==1:
ans = n
else
: left, right =
1, n
while left <= right:
mid =
(left + right)
>>
1 t1 = dp(k-
1, mid-1)
t2 = dp(k, n-mid)
if t1 < t2:
left = mid+
1elif t1 > t2:
right = mid-
1else
:break
ans =
max(dp(k-
1, mid-1)
, dp(k, n-mid))+
1 memo[k, n]
= ans
return memo[k, n]
return dp(k, n)
還有一種更加巧妙的方法。我就放上鏈結不再討論了。 高樓扔雞蛋
雞蛋數量為m,高樓層數為n,使用最小次數p去找到扔下雞蛋會碎的最小層數 首先第0層,則p 0 雞蛋數量m 0時,則p無法計算,也預設為p 0 然後第1層,則p 1 雞蛋數量m 1時,則最壞情況 p n 可以假設從k層扔下,倘若碎了,題目就變成了雞蛋數量為m 1,樓層則變為了k 1,扔蛋最小次數p 1...
每日一道演算法題 高樓扔雞蛋問題 動態規劃問題
題目是這樣 你面前有一棟從 1 到n共n層的樓,然後給你k個雞蛋 k至少為 1 現在確定這棟樓存在樓層0 f n,在這層樓將雞蛋扔下去,雞蛋恰好沒摔碎 高於f的樓層都會碎,低於f的樓層都不會碎 現在問你,最壞情況下,你至少要扔幾次雞蛋,才能確定這個樓層f呢?首先我們來看一下,什麼叫做最壞情況下,至少...
妙 高樓扔雞蛋的數學解法
數學方法 參考 關於高樓扔雞蛋問題,本文只對動態規劃方法進行概括性的描述,具體看這裡。k個雞蛋 n 層樓,問至少嘗試多少次可以找到雞蛋不碎的臨界樓層,求最少次數m 設dp k n 表示k個雞蛋n層樓要嘗試的最少次數 dp k n min 1 x n min min1 x n max dp k 1 x...