会社でアドベントカレンダーをやっているので、それに便乗して記事を書く。

何を書けばいいのか悩んだけど、今 [[LeetCode]] 1 が楽しいな〜と感じているので、そのことについて書くことにした。

LeetCode とは

LeetCode とは、プログラミングの問題を解くサイト。問題文 (英語) を読んで、渡されたインプットに対して求められるアウトプットを返す関数を書けたらOK。でも自分の書いたロジックがまずいと、いくら正しいアウトプットを返せても、計算量が多くなって制限時間オーバー (TLE: [[Time Limit Exceed]]) で NG になったりする2

自分はいわゆる[[競技プログラミング]]の文脈でこのサイトを知ったけど、海外ではテック企業に入るときにこういうコーディングテストがマストらしい。

なんで LeetCode をやっているか

今の会社に入社してからは仕事 を言い訳にして に必死で競プロからは離れていたけど、最近 『世界一流エンジニアの思考法』 を読んで学習欲が再燃した。

LeetCode は前から存在自体は知っていたが、英語オンリーということもあって敷居が高く感じてしまい、手が出せていなかった。でもプログラミングしながら英語も学べるの一石二鳥じゃね?と思い直して LeetCode をやってみたら、 AtCoder をやっていたときよりも基礎的なアルゴリズムを学べている3という感覚 (手応え?) があった。それが面白くて今まで続いている。

どう取り組んでいるか

LeetCode には 問題がめちゃくちゃたくさん あって、最初はどれから手をつけたらいいか分からなかったが、問題ごとに Difficulty が設定されているのでとりあえず上から順番に Easy の問題を解いていく4、みたいなことができる。というか自分はそうしている。

あとは Top Interview 150 - Study Plan - LeetCode みたいな「これはやっとけ」的な問題まとめがあるので、そこから面白そうな問題を選んで解いたりもしている。ジャンルが満遍なく網羅されていてよき。

気力があれば、実行速度が速い他のユーザーのコードや、解法をシェアしているユーザーの記事を参考にしてみたり、別の言語で同じ問題を解き直してみたりとかしている。

コンテストもあるらしいけど、自分はまだ怖くて参加していない。じっくり解ける今の取り組み方で十分楽しいけど、力がついてきたと感じたら参加してみてもいいのかもしれないと思っている。

まとめ

プログラミング未経験で、何から勉強したらいいか全く分からなかったときに、知り合いのエンジニアから「これやるといいよ」と聞いたのが競技プログラミングだった (そのときは paiza と AtCoder をやった)。今の会社に エンジニアとして入社 できたのは競プロを通じてプログラミングを学べたおかげだと思っている。

ソフトウェアエンジニアとして仕事をしていて、プログラミング以外の知識も必要だけど、やっぱりプログラミングの技術も必要だと改めて実感している今日このごろ。これからも LeetCode でガンガンコードを書いて、強くなっていきたいと思っている。

おまけ: 最近楽しかった問題 (微ネタバレ)

Climbing Stairs - LeetCode

You are climbing a staircase. It takes n steps to reach the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

「これ、同じものを含む順列を使えばいいじゃん!」ってひらめいて、その通りのコードが Accepted したのがすごく嬉しかった5。あと Ruby で階乗を実現しようとした際に [[reduce]] や [[inject]] の使い方を知れて、普段のプログラミングでも活かせる知識が得られたのも嬉しかった。

実際に自分が submit したもの (リンク先は登録・ログインしないと見れない)↓
https://leetcode.com/problems/climbing-stairs/submissions/1112906001

# @param {Integer} n
# @return {Integer}
def climb_stairs(n)
    p = n # 1の数
    q = 0 # 2の数
    ans = 0

    while p >= 0

        fact_p_plus_q = (1..(p + q)).reduce(:*)
        fact_p = (1..p)&.reduce(:*) || 1
        fact_q = (1..q)&.reduce(:*) || 1

        # 1が p 個、2が q 個、合計 p+q 個あるとき
        # これらを全部使って1列に並べる順列の総数は (p+q)!/p!q! 通り
        ans += fact_p_plus_q /  (fact_p * fact_q)

        p -= 2
        q += 1
    end

    ans
end

  1. ※ [[これ]] は Obsidian の内部リンク。Obsidian を使って記事を書いており、このリンクがあると情報整理に何かと都合が良いのです。読み見づらかったらごめんなさい。 ↩︎

  2. 愚直に総当たりで解いてみて、これだと計算量多くてだめだろうなと思いながら submit して、TLE になって、やっぱりだめだよな〜どう解くんだろうな、という流れをよくやる。 ↩︎

  3. LeetCode と AtCoder の違いについて、へ〜!確かに!って思ったツイート。基本の LeetCode、応用の AtCoder って感じなのかな。

    ↩︎

  4. まだ難易度 Medium までしかやってない。Hard やらねば。 ↩︎

  5. 同じものを含む順列の解き方は忘れてたのでググりました。 ↩︎