LeetCodeで何百問も解いたのに、面接本番で見たことのないタイプの問題が出て頭が真っ白になった。そんな経験をした人は少なくないはずだ。問題を数多くこなすことも大切だけれど、それ以上に「パターンを見抜く力」が面接突破の鍵を握っている。LeetCodeには数千の問題が登録されているが、出題される問題の多くは限られたパターンの組み合わせで構成されている。このパターンを体系的に理解しておけば、初見の問題でもアプローチが見えてくる。
この記事では、コーディング面接で特に頻出するアルゴリズムパターンを7つ取り上げて、それぞれの考え方や代表問題、実践で役立つ解法のコツを詳しく解説する。LeetCodeに取り組み始めたばかりの人も、すでに100問以上解いているが伸び悩みを感じている人も、パターン認識のフレームワークを手に入れることで学習効率は格段に上がるだろう。
LeetCodeのパターン学習が面接対策に効く理由
コーディング面接では、45分という限られた時間の中で問題を理解し、アルゴリズムを設計し、コードに落とし込む必要がある。この短い時間で成果を出すには、問題を読んだ瞬間に「あ、これはあのパターンだな」と気づけるかどうかが勝負の分かれ目になる。パターンを知らない状態でゼロから考えるのと、過去に身につけた型をベースに応用するのとでは、到達できるスピードがまるで違う。
そういえば、プロの将棋棋士が「定跡」を大量に暗記しているのと似た話かもしれない。定跡を知っていれば序盤で時間を節約して、終盤の複雑な局面に集中力を振り向けられる。コーディング面接におけるアルゴリズムパターンもまさに同じで、基本パターンをしっかり身につけておくことで、問題固有のひねりや制約条件への対応に頭のリソースを使えるようになる。
LeetCodeの問題をカテゴリ別に分析すると、上位テック企業の面接で出題される問題の約80%は、7つ程度の主要パターンでカバーできることがわかっている。つまり、闇雲に問題数を増やすよりも、これらのパターンを一つずつ確実に自分のものにしていく方が、効率的かつ実戦的な面接対策になる。
Two Pointers(2つのポインタ)パターン
Two Pointersは、ソートされた配列や連結リストに対して2つのポインタを使い、特定の条件を満たす要素の組み合わせを探すテクニックだ。典型的な例としては、ソート済み配列から合計が特定の値になるペアを見つける「Two Sum II」や、配列から重複を取り除く「Remove Duplicates from Sorted Array」がある。このパターンの魅力は、ナイーブな二重ループのO(n^2)をO(n)に改善できる点にある。
実際の面接では、Two Pointersはそのまま出題されることもあれば、他のパターンと組み合わさった形で登場することも多い。たとえば「3Sum」は、外側のループでひとつ固定して内側でTwo Pointersを使うという合わせ技になっている。このように、基本パターンを単体で理解するだけでなく、組み合わせの引き出しを持っておくことが面接では重要になる。
Two Pointersを使うべきかどうかの判断ポイントは、入力がソート済みか、あるいはソートしても問題ないかどうかだ。もうひとつの判断材料として、「対になる2つの要素を探す」「部分列の条件を調べる」といった問題の特徴が挙げられる。問題文を読んで「何かペアっぽいな」と感じたら、Two Pointersの適用を検討してみよう。代表問題としてはLeetCode 167(Two Sum II)、15(3Sum)、11(Container With Most Water)あたりから始めると、パターンの感覚がつかみやすい。
Sliding Window(スライディングウィンドウ)パターン
Sliding Windowは、配列や文字列の連続する部分列に対して、ウィンドウを左端から右端へスライドさせながら最適解を求めるテクニックだ。ウィンドウのサイズが固定の場合と、条件に応じて伸縮する可変サイズの場合がある。このパターンを知っているかどうかで、問題の解法がまったく変わってくる。
固定サイズのSliding Windowは比較的わかりやすい。たとえば「サイズkの連続部分配列の最大和を求める」という問題では、ウィンドウを1つ右にずらすたびに、左端の要素を引いて右端の新しい要素を足すだけでよい。これで毎回k個の要素を再計算する必要がなくなり、O(nk)がO(n)に改善される。難しいのは可変サイズの方で、「条件を満たす最短の部分配列」や「すべての文字を含む最小のウィンドウ」といった問題になると、ウィンドウの右端を伸ばすタイミングと左端を縮めるタイミングの判断が必要になる。
面接で頻出のSliding Window問題としては、LeetCode 3(Longest Substring Without Repeating Characters)が鉄板だ。この問題では、ハッシュマップと組み合わせて各文字の出現位置を追跡しながら、重複が見つかるたびに左端を移動させる。ほかにもLeetCode 76(Minimum Window Substring)やLeetCode 438(Find All Anagrams in a String)は、Sliding Windowの応用力を高めるのに最適な練習問題だ。ウィンドウの状態管理にハッシュマップを使うパターンは本当に頻繁に出るので、必ず手に馴染ませておこう。
BFS/DFS(幅優先探索/深さ優先探索)パターン
グラフやツリーの探索は、コーディング面接において避けて通れないテーマだ。BFS(幅優先探索)とDFS(深さ優先探索)はどちらもグラフ探索の基本手法だが、問題によって使い分ける必要がある。ざっくり言うと、最短距離や最少手数を求めるときはBFS、すべてのパスを列挙したり条件を満たすパスが存在するか調べたいときはDFSが向いている。
BFSはキューを使って実装するのが定番で、現在のノードから距離1のノード、距離2のノードと層ごとに探索を広げていく。ツリーのレベルオーダートラバーサル(LeetCode 102: Binary Tree Level Order Traversal)がBFSの入門として最適だ。この問題を解くことで、キューの使い方やレベルごとの処理の書き方が身につく。グラフの問題に発展すると、「訪問済みかどうか」のチェックが必要になるので、visited配列やセットの管理も合わせて練習しておこう。
DFSは再帰で書くことが多く、バックトラッキングと密接に関連している。ツリー構造の問題では、LeetCode 104(Maximum Depth of Binary Tree)やLeetCode 226(Invert Binary Tree)といったシンプルな再帰問題から入るのがおすすめだ。実は、DFSで再帰を使うかスタックで反復的に書くかは面接官によって好みが分かれることもあるので、両方のスタイルで書けるようにしておくと安心だ。グリッド上の島の数を数える問題(LeetCode 200: Number of Islands)は、DFSの実践力を試すのに絶好の問題なので、ぜひ取り組んでほしい。
Binary Search(二分探索)パターン
二分探索は「ソート済み配列から目的の要素を見つける」というシンプルなイメージがあるかもしれないが、面接で出題される二分探索の問題はもっと奥が深い。答えに対して二分探索を適用する「答えで二分探索」というテクニックや、回転ソート配列での探索、行列における二分探索など、バリエーションが豊富だ。
二分探索の最も厄介な部分は、境界条件の処理だろう。leftとrightの初期値をどう設定するか、ループ条件をleft < rightにするかleft <= rightにするか、midの計算でleft + (right - left) / 2を使う理由は何か。こうした細かいポイントを曖昧にしたまま面接に臨むと、紙の上では正しく見えるコードが実際にはエッジケースで無限ループを起こすことがある。二分探索を練習するときは、small input(配列長1や2)で動作確認する習慣をつけておくと、本番でのバグを防げる。
代表的な練習問題としてはLeetCode 33(Search in Rotated Sorted Array)がまず挙げられる。この問題は「どちら側がソートされているか」を判定するステップが入るため、純粋な二分探索の延長として理解しやすい。さらにLeetCode 875(Koko Eating Bananas)は「答えで二分探索」の典型例で、答えの範囲を二分探索しながら条件を満たす最小値を見つける。このタイプの問題に慣れると、一見二分探索に見えない問題でも「もしかして答えで二分探索できるのでは」と発想できるようになる。
Dynamic Programming(動的計画法)パターン
動的計画法、通称DPは、コーディング面接で最も恐れられているトピックのひとつだ。「DPが出たら終わり」と感じている人も多いかもしれないが、実際にはDPの問題にもパターンがあり、そのパターンを知っていれば対処できる問題は格段に増える。DPの本質は「大きな問題を小さなサブ問題に分解し、サブ問題の答えを再利用すること」にある。
DPの問題を解くときの鉄則は、状態の定義と遷移式の設計だ。たとえばLeetCode 70(Climbing Stairs)では、dp[i]を「i段目に到達する方法の数」と定義すると、dp[i] = dp[i-1] + dp[i-2]という遷移式がすぐに導ける。この感覚を基盤にして、LeetCode 322(Coin Change)やLeetCode 300(Longest Increasing Subsequence)へとステップアップしていくのが効率的な学習ルートだ。DPの問題を見たときに「何を状態として持つか」をまず考える癖をつけておこう。
ところで、面接でDPの問題が出た場合、いきなりDP解法を書き始めるのは得策ではない。まず再帰的なブルートフォース解を考え、そこにメモ化を加え、必要に応じてボトムアップのテーブル解法に変換するという段階を踏むのがよい。面接官はこのプロセスを見たがっていることが多い。再帰からメモ化、メモ化からテーブルDPへの変換ができることを示せば、問題を完全に解ききれなくても高い評価を得られる可能性がある。DPの頻出パターンとしては、0-1ナップサック型、文字列のDP(LCS、Edit Distance)、区間DP、木DPなどがあるので、それぞれ1-2問ずつ練習しておくとよいだろう。
Backtracking(バックトラッキング)とGreedy(貪欲法)パターン
バックトラッキングは「すべての候補を試して、条件に合わないものは途中で打ち切る」という探索手法だ。順列や組み合わせの列挙、数独のソルバー、N-Queens問題などが代表的な応用例で、DFSの一種と捉えることもできる。バックトラッキングの問題を解くコツは、「選択→探索→元に戻す」というテンプレートを体に染み込ませることだ。
LeetCode 46(Permutations)やLeetCode 78(Subsets)は、バックトラッキングの入門として最適な問題だ。これらの問題を通じて、再帰の各レベルで「何を選ぶか」を決定し、選択を記録して次のレベルに進み、戻ってきたら選択を取り消すという一連の流れを練習する。面接では、この基本テンプレートをベースにしつつ、枝刈り(pruning)の条件を追加することで計算量を削減する工夫が求められることも多い。たとえばLeetCode 39(Combination Sum)では、重複を避けるためのインデックス管理がポイントになる。
一方、貪欲法は「その時点での最善の選択を繰り返すことで全体の最適解に到達する」というアプローチだ。貪欲法が正しく機能する問題かどうかの判定は簡単ではないが、面接で出る貪欲法の問題にはいくつかの典型的なパターンがある。LeetCode 55(Jump Game)やLeetCode 134(Gas Station)が代表例で、これらの問題では「現在の状態から到達可能な範囲」を貪欲に更新していくことで解ける。貪欲法の問題は、正しさの証明が難しいことがあるが、面接では直感的な説明と反例がないことの確認ができれば十分な場合が多い。
パターン認識力を鍛えるための実践的な学習戦略
パターンを知識として知っているだけでは、面接本番で使いこなすことはできない。知識を実戦力に変えるには、意図的な練習方法が必要だ。最も効果的なのは「パターンごとにまとめて解く期間」と「ランダムに解く期間」を交互に設けることだ。
パターン集中期間では、ひとつのパターンにつき5-10問を連続して解く。同じパターンの問題を続けて解くことで、問題文のどこに着目すればそのパターンだと判断できるかという感覚が養われる。たとえばSliding Windowの問題を5問連続で解くと、「連続する部分列」「条件を満たす最小/最大」「重複なし」といったキーワードが目に飛び込んでくるようになる。この段階では、解けなかったら20分程度で解説を見て、翌日にもう一度自力で解き直すサイクルが効率的だ。
ランダム期間では、パターンを指定せずに問題を解く。この段階の目的は「パターンの判定力」を鍛えることだ。問題を読んで、どのパターンが適用できそうか仮説を立ててから解き始める。この仮説が外れることも当然あるが、その失敗経験こそが学びになる。「Two Pointersだと思ったけど、実はSliding Windowだった」という経験を積むことで、パターン判定の精度が上がっていく。LeetCodeのDiscussタブで他の人の解法を読む習慣も大切で、自分とは違うアプローチに触れることでパターンの引き出しが広がる。
学習の記録をつけることもおすすめしたい。問題番号、使ったパターン、解けたかどうか、詰まったポイントをスプレッドシートなどに記録していくと、自分の弱点が客観的に見えてくる。「DPは得意だけどグラフ問題が苦手」「二分探索の境界条件でいつもバグる」といった傾向が把握できれば、残りの準備時間をどこに投資するかの判断がしやすくなる。
面接本番でのパターン活用術
実際の面接では、いきなりコードを書き始めるのではなく、問題を分析する時間を確保することが大切だ。面接官が問題を提示したら、入力と出力の例を確認し、制約条件を整理して、エッジケースを洗い出すところから始めよう。この分析の過程で「配列がソート済み」「連続する部分列」「最短経路」といったヒントが見つかれば、適用すべきパターンがおのずと絞り込まれてくる。
面接中に使えるテクニックとして、パターンの候補を声に出して面接官と共有する方法がある。「この問題はソート済み配列なので、二分探索かTwo Pointersが使えそうです」と言えば、面接官が「いい方向ですね」とか「もう少し別のアプローチも考えてみてください」とヒントをくれることがある。コーディング面接はコミュニケーションの場でもあるので、思考プロセスを見せることで部分点を稼げる。
ところで、パターンがすぐに見つからないときの対処法も知っておくべきだ。そういうときは、まずブルートフォース解を考えてみる。ブルートフォースの計算量を分析して、どこにボトルネックがあるかを特定し、そのボトルネックを解消するパターンを探す。「この二重ループを一重にできないか」と考えればTwo PointersやSliding Windowが候補に上がり、「この探索を高速化できないか」と考えればBFSやBinary Searchが浮かんでくる。パターン認識は最初の直感だけに頼るものではなく、段階的に絞り込んでいくプロセスなのだ。
まとめ
LeetCodeの頻出パターンを体系的に学ぶことは、コーディング面接を効率よく攻略するための王道アプローチだ。Two Pointers、Sliding Window、BFS/DFS、Binary Search、Dynamic Programming、Backtracking、Greedyという7つの主要パターンをしっかり押さえておけば、面接で出題される問題の大部分に対応できる。
パターンを知るだけでなく、繰り返し練習して体に染み込ませることが何より大切だ。集中学習とランダム学習を組み合わせ、学習記録をつけて自分の弱点を可視化し、面接本番ではパターン判定のプロセスを面接官と共有しながら進めていこう。地道な積み重ねが、面接本番での自信と結果につながるはずだ。