Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
問題へのリンク
Paint Fence - LeetCode
言語
Python
問題の概要
n
本のフェンス(のポスト)があり、k
色のペンキを使って塗るn
本のフェンスを塗る方法の数を求めよ自分の解法: Bottom-Up DP
n
本のフェンスを塗る方法の数をn
についての漸化式で求める。k
は固定して考える。n
本のフェンスを塗る方法の数を求めるために、以下のように考える。n
本目とn-1
本目のフェンスが同じ色でない場合n
本目のフェンスはk-1
色から選べる。1
本目からn-1
本目のフェンスを塗る方法の数はcount[n-1]
となる。n
本目とn-1
本目のフェンスが同じ色である場合、n
,n-1
本目のフェンスはk-1
色から選べる。1
本目からn-2
本目のフェンスを塗る方法の数はcount[n-2]
となる。したがって、
count[n]
をn
本のフェンスを塗る方法の数とすると、count[n] = (k - 1) * count[n - 1] + (k - 1) * count[n - 2]
count[1] = k
,count[2] = k * k
(n = 2
の場合は、どの色を選んでも隣接するフェンスと同じ色にならないため)とを併せて考えると、count[n]
がn
回のループで求まる。動的計画法の配列は使わず、
count[n-1]
とcount[n-2]
の値を保持する変数を用いて計算することで空間計算量をO(1)
に抑える。O(n)
O(1)
step1
step2
count
という変数名は曖昧すぎたのでtotal_ways
などに変更した。O(log n)
時間 で解くこともできる。O(log n)
という計算量解析には注意が必要。そのまま答えの値を計算するだけで考えると桁数が大きくなるため、足し算や掛け算が定数時間とみなせなくなる(大きい数ほど一度の計算に時間がかかる)可能性がある。ある数で割った余りを求めるなどの処理を行う場合は、O(log n)
で計算できると考えられる。step3
いつも1次元DPで、いくつかの変数を逐一、更新していく際には
tmp_foo
という一時変数を使って、元の値を保持しておくことが多かった。が、unpackして更新したほうが、コードが短くなり、可読性も上がるので、今後はできるだけこの書き方を使うことにしたい。ただし、上の例のように少し処理が複雑になると、可読性が下がるので難しいところもある。step4 (FB)
別解・模範解答
メモ化再帰(hayashi-ayさんの解答)
276. Paint Fence by hayashi-ay · Pull Request #17 · hayashi-ay/leetcode · GitHub
メモ化再帰を用いて解く方法。
@cache
デコレータを用いて、計算済みの値をキャッシュすることで、再帰的な計算を効率化している。時間計算量:
O(n)
空間計算量:
O(n)
(スタックの深さが最大n
になるため)cacheについて
@cache
デコレータも自作してみて、自分なりに調べた内容をまとめて技術記事にした。Python functools.cacheを自作してみた。キーワード引数のキャッシュの仕様には注意 - Qiita組み合わせの数を分けて数えて、最後に足す方法
つぎの2つのケースに分けて考える。
それぞれを別に計算して、最後に足す。
次に解く問題の予告