子供が産まれて、育休を取り始めました

この度、赤ちゃんが生まれました。 めでたい。 そんでもって、10月から半年ほど育休を取って、育児に専念することになりました。 会社・部署の方々など、様々な方のサポートがあってのことです。 とても感謝しています。 休み自体は9月のシルバーウィークから取っていて、すでに絶賛育児中です。 ただね…… この時点ですでに大変なんだが? 細かいポイントを含めれば色々あるけど、しんどかったポイントをあげるなら、こんな感じ。 1. 生活リズムが不規則になる 私の担当範囲は、起きている時間のミルク、おむつ替え、沐浴、暇な時にじっと赤ちゃんの様子を見つめるなど。(あれ、意外とやってないな……) 主に昼から夜、あとは深夜から朝方(1時〜7時)に起きている感じ。 深夜に起きる前と、朝の担当が終わったあとに、それぞれ3〜4時間程度寝ている。 元々深夜に作業するのが苦じゃないタイプなので、深夜も赤ちゃんが寝ている時などは、パソコンでAIと戯れたり、スマホでダラダラとこんな感じの記事を書いたりと好き勝手やっている。 が、最初の方は生活リズムを変えるのがしんどかった。 無理やり寝るためにサプリメントを飲んだり、とにかく横になったりと色々試したが、寝れない時はとにかく寝れない。これがしんどい。 結局、慣れるまではどうにもならなかった。 人間って生活リズムを変えるのが難しい生き物なんだな、と割り切ることにした。 一方、妻の側は、今のところだいたい3時間おきに授乳がある。 母乳だったり、ミルクだったり、その併用だったり。 これがシンプルながらに、妻への負担が半端ない。 妻は授乳のたびに起きているし、赤ちゃんの空腹具合によっては泣き声と共に叩き起こされたりと、不規則な睡眠を強いられている。 授乳の間隔が空くと胸が張るし、乳腺炎になることもあるそう。 発熱などが出ることもあるので、妻の体調も気になる。 うちは基本的に母乳をあげて、足りない分はミルクを作って補う感じで運用している。 育児を始める前は、12時間ずつ分担して、私のターンはミルク、妻のターンは母乳でいいんじゃない?とか考えていた。 が、現実はそんなに割り切れるようにはなっていなかった。 赤ちゃんの都合だけじゃなく、妻の体の事情もある。 あと、沐浴とかも...

「問題解決力を鍛える!アルゴリズムとデータ構造」とLeetCodeで学ぶ再帰と動的計画法(メモ化)

再帰とメモ化

問題解決力を鍛える!アルゴリズムとデータ構造
というアルゴリズムとデータ構造を学ぶのに良い本があります。

LeetCodeの問題を解いていた時に、この本の中で解説されていた例とすごく被っている内容があったので、記事にしてみようと思いました。

問題

1137. N-th Tribonacci Number

難易度はEasy。
再帰の入門にうってつけです。

問題解決力を鍛える!アルゴリズムとデータ構造の4章の解説にもある通り、再帰関数のテンプレートは

(戻り値の型) func(引数){
	if(ベースケース){
		return ベースケースに対する値;
	}
	func(次の引数)
	return 答え
}

問題解決力を鍛える!アルゴリズムとデータ構造 第4章 設計技法(2):再帰と分割統治法より引用

といったものです。

今回解く問題は、

トリボナッチ数列Tnは次のように定義される。

T0 = 0, T1 = 1, T2 = 1, そして n >= 0 で Tn+3 = Tn + Tn+1 + Tn+2 となる。

nが与えられたとき、Tnの値を返す。

という内容です。

では、こちらをPythonでかつ再帰で解いてみましょう。

class Solution:
    def tribonacci(self, n: int) -> int:
        if n == 0:
            return 0
        elif n == 1 or n == 2:
            return 1
        return self.tribonacci(n-1) + self.tribonacci(n-2) + self.tribonacci(n-3)
# Time Limit Exceeded

しかし、これだとnが 30の時に時間切れとなり、正解とは認められません。

これは再帰で同じ処理が重複し、関数の呼び出し回数がとてつもない回数になっているためです。

ではこれを解決してみましょう。

class Solution:
    def tribonacci(self, n: int) -> int:
        memo = collections.defaultdict(int)
        memo[0], memo[1], memo[2] = 0,1,1
        for i in range(3,n+1):
            memo[i] = memo[i-1] + memo[i-2] + memo[i-3]
        return memo[n]
# Runtime: 28 ms, faster than 80.87% of Python3 online submissions for N-th Tribonacci Number.
# Memory Usage: 14.3 MB, less than 13.79% of Python3 online submissions for N-th Tribonacci Number.

この解法では一度計算したものをmemoという変数に保存し、仮に計算済みであれば関数を呼び出すのではなく値を直接返すようにしています。これをキャッシュといい、高速化するための手法です。

どうでしょうか。

これ以外にも問題を解決するための思考法などが満載の素晴らしい本なので、問題解決力を鍛える!アルゴリズムとデータ構造を買って実際に勉強されてみるといいかと思います。

今回はここまで。お疲れ様でした。

Comments

Popular posts from this blog

Braveブラウザ(iPhone,iPad)にオフラインでもYouTubeの動画が視聴可能なPlaylist機能が追加されていたので使い方をまとめてみた。

Braveブラウザの同期機能をiPhoneで設定した話。

【OSLog】How to log a Swift project