データ構造とアルゴリズムを再勉強したのでおすすめの勉強法を書く
ども、Nash です。
この記事は「データ構造とアルゴリズムについて勉強しなおした話」についての記事です。
それと合わせておすすめの勉強法をまとめます。
では、見ていきます。
どうやって学んだ
自分のケースでは、いくつかの方法で学びました。
- CICCC の Algorithm の授業を受けた
- 技術本を読んで学んだ
- LeetCode を解いて学んだ
- 動画を見て学んだ
結果論ですが、授業はなくても十分独学だけでも学習は可能でした。
1つずつみていきます
CICCC
機会があり、バンクーバーにある CICCC という学校の Web&Mobile の中で Data structure and Algorithm の授業を受けました。
授業内容については、基本的なデータ構造とアルゴリズムの学習から始まり、2〜3日ごとの課題のコードを提出して、最後のテストで基準点を超えることが Criteria でした。
普通に日本で生活している人からすると「そんなん受けられんわ」となるかと思いますが、授業内容は後述する技術本で十分網羅されてます。
あとあとにおすすめの勉強法を書きますが、独学で進めるなら技術本だけでも十分でした。
技術本
アルゴリズム関連について自分が読んだ本です。
読後レビュー|『なっとく!アルゴリズム』わかりやすさに特化した入門書
読後レビュー|『世界で闘うプログラミング力を鍛える本 コーディング面接 189 問とその解法』
読後レビュー|『問題解決力を鍛える!アルゴリズムとデータ構造』
後述しますが、インプットについてはこれらの本だけでも十分かと思います。
LeetCode
AtCoder でもいいですが、個人的にはグローバルスタンダードな LeetCode をおすすめしておきます。
LeetCode は Easy/Medium/Hard の3つのレベルに分かれています。 自分は割となめてかかったので、Easy で出来ない問題とかにあたってショックを受けてましたが、はじめての競技プログラミングだとすれば Easy でもクリアできない可能性が高いので気にしないでください。
解いてもわからなければ早めに答えを見て、解法を覚えて、次に解けられるようにする、というサイクルを早く回すほうが効率がいいです。 解法は、LeetCode の Disscussion か問題名+ No で検索すれば記事だけでなく YouTube で説明してる動画がすぐに見つかると思います。
動画
技術本や LeetCode などで読んでも理解できないものは、YouTube などで学習します。
もちろん、動画ファーストな学習方法でもいいと思います。個人的には技術本のほうが学習プランが綺麗に進められるかと思っているので、おすすめは本で学習しつつわからなければ動画をみる、というスタンスでした。
というわけで、これらのコンテンツを使って学習をしました。
次におすすめの学習方法を紹介します。
おすすめの学習方法
ビジュアライズ化したコンテンツ
まず、こちらのアプリを購入しておくことを強く推奨します。
このアプリは、アルゴリズムの動きをアニメーションでビジュアライズ化しつつ説明してくれます。技術書も出ていますがアニメーションが見れないのであまり意味がないので、アプリ版の購入を強くすすめます。
また、あくまでこのアプリはメインの教材の補足として使うのがいいかと思います。
ちなみに、ビジュアライズ化した説明については YouTube で探せば見つかりますが英語かつ品質のばらつきがあるので、調べるコストとかを考えるとこのアプリを買っちゃうほうがはるかに安上がりです。
技術書を1つずつ読んでいく
技術書をレベル順に1つずつ読んでいきます。
読む順番についてはのおすすめはこの順番です。
- 「なっとくアルゴリズム」
- 「世界で戦うプログラミング力」
- 「問題解決力を鍛える」
人によっては、なっとくアルゴリズムは不要だったり、もしかすると非エンジニアの場合は更に簡単な本が必要な可能性もありますが、個人的には万人におすすめできる順番がこれです。
LeetCode で解く
技術書で出てきた単元について、深堀りをしたいなら LeetCode で探して類似の問題を解きます。
とはいえ、「世界で戦うプログラミング力」は問題集になってるので、これだけでもかなりの問題があるので、LeetCode が不要な可能性もありますが、ずっと本を読んでても疲れるし慣れるためにも LeetCode の併用をおすすめします。
というわけで、おすすめの勉強コンテンツと流れでした。
自分のおすすめ参考にしつつ自分にあったコンテンツ・やり方を見つけられれば幸いです。
データ構造とアルゴリズムを学びなおしての気付き
学びなおしてわかったことを書いていきます。
日常の開発への影響
正直な話、データ構造とアルゴリズムを学んでもだと日常の仕事に劇的な変化はまったくありません。
自分のいまの仕事が Frontend だからなのと以前は Fullstack だったので Backend 側の仕事も理解していますが、どちらにしても変わらないだろうなーと思います。
もっと低級レイヤーに携わったり、ミドルウェア開発をしている場合はここらへんについて得られるものもあるかもしれません。 ですが、少なくともアプリケーションレイヤーを開発している立場の人からすると学習コストに対して得られるリターンについて短期的にはかなり少ないです。
個人的な意見として、Fundamental な知識の重要性は長期的な目線で考えるべきなので短期的には得られるリターンは少ないのは予想通りです。
今後、自分の長期的なキャリアにおいてこの知識が伏線よろしくに効いてくれる可能性を考えています。
すぐに忘れる
数ヶ月前にアルゴリズムについてゴリゴリと勉強して、かなり記憶したはずなのですが今この記事を書いてるときに久しぶりにアルゴリズムの内容を見てもびっくりするくらい忘れてます。 アルゴリズムは記憶定着しにくいし、復習をしていないのさ自然ですが、それでもかなり絶望するくらい覚えてないです。
Algorithm を教えてくれた先生曰く、「数カ月後には全部忘れてる。けどまた、学習すれば前よりも遥かに短い時間で思い出すから大丈夫」と言われたのを思い出しますがそれでもショックですね。。。
なので、アルゴリズムの学習についてはそれなりに長期的に取り組むか、逆にゴールがあるなら短期的にインプットして詰め込むほうがいいかもしれないですね。
データ構造とアルゴリズムの学習の前に理解すること
「仕組みの理解」と「コードによる実装」を分けてフェーズを進めるべきです。
データ構造とアルゴリズムの学習にて、最終的なアウトプットでコードになることからこの2つのフェーズを同時におこなったり、理解をおざなりにしてコードから手を付けると遠回りになります。
-
「仕組みの理解」として、相手に説明できること、たとえばソートアルゴリズムなら紙に書いてその動きをステップごとにトレースできること。
-
「コードによる実装」として、アルゴリズムをプログラミングの領域に落とし込む。再帰関数・ループ処理・分岐処理あたりがポイントになりやすい。
あくまで「仕組みの理解」が前提にあって、それを「コードによる実装」へ落とし込みます。
もし、データ構造とアルゴリズムにおいて詰まることがあれば、「仕組みの理解」が甘いケースの疑いを持ってコードを書く手を止めて、理解できているか再度考えることをおすすめします。
学んだ内容
さて、最後に自分が学んだデータ構造とアルゴリズムについての内容を備忘用に列挙していきます。
-
基礎:Big O Notation / Brute-force search / Recursion (dfs/bfs) / Memoization
-
データ構造:HashMap / LinkedList / Heap / Graph / Tree / Union-find
-
ソート:Bubble / Merge / Insertion / Selection / Heap / Quick
-
アルゴリズム:Dynamic Programming / Binary Search / Dijkstra / Bellman-ford / Floyd-warshall / Topological Sort / MST by Prim / MST by Kruskal
アルゴリズムの解説とか記事
学びながら書いた記事です。学んだアルゴリズムを使って解いた問題に対する解説記事です。
Graph の Path 系
- Swift で Dijkstra Algorithm(ダイクストラ法)使って SSSP:Single Source Shortest Path(単一始点最短経路問題) - Qiita
- Swift で Bellman-Ford Algorithm (ベルマンフォード法)使って SSSP:Single Source Shortest Path(単一始点最短経路問題) - Qiita
- Swift で Floyd-Warshall Algorithm (ワーシャル・フロイド法)使って APSP:All Pair Shortest Path(全点対最短経路問題) - Qiita
DP 系
- Swift で Edit Distance (編集距離) - Qiita
- Swift で Kadane’s Algorithm 使って Maximum Subarray(最大部分配列) - Qiita
- Swift で LCS:Longest Common Subsequence(最長共通部分列) - Qiita
- Swift で LCS:Longest Common Substring(最長共通部分文字列) - Qiita
Graph のソート
MST 系
- Swift で Kruskal(クラスカル法)使って MST:Minimum Spanning Tree(最小全域木) - Qiita
- Swift で Prim(プリム法)使って MST:Minimum Spanning Tree(最小全域木) - Qiita
Tree 系
Recursion 系
おわりに
今年は時間を取って、データ構造とアルゴリズムについて学びなおしました。
自己満足という観点で言えば、かなり満足しています。
ただ、すでにかなりのアルゴリズムを忘れてしまっているのは少し悲しいですね。
きちんと自分が理解できるように記事にして整理してはあるので、あとあと時間をとって1つずつ思い出しながら復習してがんばって定着させていこうと思います。