こんにちは
今回の学びは
・ある程度型、パターンを覚えて、解く・閃く速度をあげよう (これ結構大事かも)
・配列がサイクリックになったら、ズラして2パターンを解く
問題は。。。
(時間配分は5分問題理解 10分検討 10分実装 20分振り返り の一文45分構成)
まずは入出力をしっかりおさえましょう。
leetcode easy 198 house robberという問題で
与えられた配列はサイクリックであるとう違いのみです。
ですが
この違いを埋めるアイデアの思いつきは結構難しかったです
例のごとくエクセルにdp表を書きながらあーだ、こーだしました。
何かしらの筆跡はわかると思いますが、(これくらいのサンプルをあーだこーだした様子がわかると思うので、後の自分の参考になる
と思ってスクショしています。)最後の方で

top includedしたバージョンと、その場合の答えはi-1
top excludedしたバージョン この場合の答えはi
というしたらいけそうだということが分かり、それがそのまま正解となった
最初の数字を使ってしまうと、それが伝搬されて最終的に最後の数字が使えなくなる。
だから
どうしたらいいんだ?的な発想が発見につながったと思います
肝は最初の数字が貢献すると最後は使えない
ということですね。
最初の25分では思いつきませんで、さらに悩むこと15分くらいしたかと思います
思いつきのスピードをあげるにはどうしたらいいのでしょうか?
=>できる人は型でと行っている記事もあるくらいなので、まぁ、パターンを自分のDBに貯めていくことをやってみましょうか。
ということで今日の私のパターンDBには配列がサイクリックになったら、ズラして2パターンを解く
と追加しました
実装前後でこれは毎回書きましょう。timespace analysis (時間とスペースの分析)は O(n)
pseudocode(擬似コード)をかいてみますか。
。。。
実際の実装はこちら
class Solution:
@timeit
def rob(self, nums: List[int]) -> int:
length = len(nums)
if length <= 0: return 0
if length <= 3: return max(nums)
# length >= 4
dp = [0] * len(nums)
def dp_get(i, default=0):
if i < 0 or i >= length: return default
else: return dp[i]
# dp的にiまでの配列をつかった最大をほりこんでいけたと仮定(hypoth1)する
# その上で漸化式をつくる
# hypothXが可能か検討する yesなら実装 noならdp以外で再試行
# Top included
for i in range(length):
dp[i] = max(dp_get(i-1), dp_get(i-2)+nums[i])
maxi = dp[i-1]
# Secound round without top
dp[0] = 0 # bit of initializtion
for i in range(1, length):
dp[i] = max(dp_get(i-1), dp_get(i-2)+nums[i])
return max(maxi, dp[i])
実装後です。timespace analysis (時間とスペースの分析)は O(n)でスペースもO(n)です
メモでコメントでかきましたが、
dpダメならと、次の手順にも目を向けているあたりは成長しているなと感じます。
速度は十分出たので満足です

メモリに関しては成績はよくないですが、他の人はdp使わずに解いたということでしょうか。
まとめ
・ある程度型、パターンを覚えて、解く・閃く速度をあげよう (これ結構大事かも)
・配列がサイクリックになったら、ズラして2パターンを解く
以上です