
コーディング面接に
文 ゆめさく ・ 公開 2026年10月30日 ・ 更新 2026年10月30日
8 つの テーマの早見表
コーディング面接の
探している
| 計算量 | 代表例 |
|---|---|
| O(1) | 添字で |
| O(log n) | 二分探索 |
| O(n) | 1 周して調べる |
| O(n log n) | ソート |
| O(n²) | 二重の繰り返し |
8 つの
| テーマ | ひとことで |
|---|---|
| 1. 計算量と | 手間の |
| 2. 配列と文字列 | 番号つきの |
| 3. ハッシュマップ | 名札つきロッカーで、 |
| 4. ソートと二分探索 | 並べて |
| 5. スタックとキュー | お皿は |
| 6. 再帰と木 | 自分を |
| 7. グラフ探索と | つながりを、 |
| 8. 動的計画法 (DP) | 途中の |
まず これだけは 解く 14 問
準備の
最優先の 8 問です。
| 問題 | 覚える型 | 計算量 (時間 / 空間) |
|---|---|---|
| Two Sum (1) | ハッシュで | O(n) / O(n) |
| Valid Parentheses (20) | スタックで | O(n) / O(n) |
| Binary Search (704) | 半分ずつ絞る | O(log n) / O(1) |
| Contains Duplicate (217) | セットで | O(n) / O(n) |
| Valid Anagram (242) | 文字の | O(n) / O(1) |
| Reverse Linked List (206) | つなぎ替える | O(n) / O(1) |
| Maximum Depth of Binary Tree (104) | 再帰で | O(n) / O(高さ) |
| Climbing Stairs (70) | DP の入門 | O(n) / O(1) |
次に
| 問題 | 覚える型 | 計算量 (時間 / 空間) |
|---|---|---|
| Best Time to Buy and Sell Stock (121) | これまでの | O(n) / O(1) |
| Valid Palindrome (125) | 両端から寄せる | O(n) / O(1) |
| Longest Substring Without Repeating Characters (3) | 窓を | O(n) / O(文字の種類) |
| Merge Two Sorted Lists (21) | 2 つの | O(n + m) / O(1) |
| Number of Islands (200) | 幅優先か | O(行 × 列) / O(行 × 列) |
| Group Anagrams (49) | 並べ替えた | O(n × L log L) / O(n × L) |
表の ( ) の
問題文の 言葉から、 使う テーマを選ぶ
面接では、
1. 計算量と オーダー記法 (手間の増え方)
たとえ 辞書で
計算量には、
| 計算量 | n が 10 | n が 100 | n が 1,000 |
|---|---|---|---|
| O(1) | 1 | 1 | 1 |
| O(log n) | 約 3 | 約 7 | 約 10 |
| O(n) | 10 | 100 | 1,000 |
| O(n log n) | 約 33 | 約 660 | 約 10,000 |
| O(n²) | 100 | 10,000 | 1,000,000 |
O(1) は
オーダー記法への
| 手間の式 | オーダー記法 | 捨てたもの |
|---|---|---|
| 3n + 5 | O(n) | 係数の 3 と |
| n² + 100n | O(n²) | 小さい |
| 繰り返しを 2 つ続ける (n + n) | O(n) | 足し算は |
| 繰り返しの | O(n²) | 掛け算は |
計算量には、
log n が
よく
| 操作 | 手間 | 補足 |
|---|---|---|
| 配列の | O(1) | 番号で |
| 配列の | O(1) | 平均して。 |
| 配列の | O(n) | 全部ずらす |
| 配列から値で探す | O(n) | 端まで見る |
| dict、 | O(1) | 平均。 |
| ソート | O(n log n) | sorted、sort |
| 並んだ | O(log n) | 半分ずつ捨てる |
| 点 n 個と | O(n + m) | 幅優先と深さ優先 |
アルゴリズムごとの
| アルゴリズム | 平均 | 最悪 | 空間 |
|---|---|---|---|
| 線形探索 | O(n) | O(n) | O(1) |
| 二分探索 | O(log n) | O(log n) | O(1) |
| バブルソート | O(n²) | O(n²) | O(1) |
| 挿入ソート | O(n²) | O(n²) | O(1) |
| マージソート | O(n log n) | O(n log n) | O(n) |
| クイックソート | O(n log n) | O(n²) | O(log n) |
| 幅優先、深さ優先 | O(n + m) | O(n + m) | O(n) |
| ダイクストラ法 | O((n + m) log n) | 同じ | O(n) |
クイックソートの
問題文に n の
| 問題文の n | 使える | その |
|---|---|---|
| 10 以下 | O(n!) 全部の並べ方 | 約 363 万 |
| 20 以下 | O(2ⁿ) 全部の選び方 | 約 105 万 |
| 100 から 200 以下 | O(n³) 三重の繰り返し | 100 万から 800 万 |
| 1,000 以下 | O(n²) | 100 万 |
| 10 万以下 | O(n log n) | 約 166 万 |
| 100 万以上 | O(n) か O(n log n) | n log n で |
| 10 の 12 乗以下 | O(√n) 約数を | 100 万 |
次の
Python
def linear(nums, t):
steps = 0
for x in nums:
steps += 1
if x == t:
break
return steps
def binary(nums, t):
lo, hi = 0, len(nums) - 1
steps = 0
while lo <= hi:
steps += 1
mid = (lo + hi) // 2
if nums[mid] == t:
break
if nums[mid] < t:
lo = mid + 1
else:
hi = mid - 1
return steps
for n in (10, 100, 1000):
nums = list(range(n))
print(n, linear(nums, n - 1),
binary(nums, n - 1))JavaScript
function linear(nums, t) {
let steps = 0;
for (const x of nums) {
steps += 1;
if (x === t) break;
}
return steps;
}
function binary(nums, t) {
let lo = 0;
let hi = nums.length - 1;
let steps = 0;
while (lo <= hi) {
steps += 1;
const mid = Math.floor((lo + hi) / 2);
if (nums[mid] === t) break;
if (nums[mid] < t) lo = mid + 1;
else hi = mid - 1;
}
return steps;
}
for (const n of [10, 100, 1000]) {
const nums = [...Array(n).keys()];
console.log(n, linear(nums, n - 1),
binary(nums, n - 1));
}実行した出力
10 10 4
100 100 7
1000 1000 102. 配列と 文字列 (番号つきの箱)
たとえ 番号の
| 添字 | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 値 | 5 | 2 | 8 | 1 |
文字列は、
配列の
| 手 | 窓の中身 | 和 | 計算 |
|---|---|---|---|
| 1 | 2、1、5 | 8 | 最初に 3 つ足す |
| 2 | 1、5、1 | 7 | 8 から 2 を |
| 3 | 5、1、3 | 9 | 7 から 1 を |
| 4 | 1、3、2 | 6 | 9 から 5 を |
Python
def max_window(nums, k):
cur = sum(nums[:k])
best = cur
for i in range(k, len(nums)):
cur += nums[i]
cur -= nums[i - k]
best = max(best, cur)
return best
nums = [2, 1, 5, 1, 3, 2]
print(max_window(nums, 3))JavaScript
function maxWindow(nums, k) {
let cur = 0;
for (let i = 0; i < k; i++) {
cur += nums[i];
}
let best = cur;
for (let i = k; i < nums.length; i++) {
cur += nums[i] - nums[i - k];
best = Math.max(best, cur);
}
return best;
}
const nums = [2, 1, 5, 1, 3, 2];
console.log(maxWindow(nums, 3));実行した出力
9要点 窓は
面接での一言
3. ハッシュマップ (名札つきロッカー)
たとえ 名札の
典型は、
| 見る数 | 必要な相方 | ロッカーの中 | そのあと |
|---|---|---|---|
| 3 | 6 | 空 | 3 を |
| 8 | 1 | 3 だけ | 8 を |
| 2 | 7 | 3 と 8 | 2 を |
| 7 | 2 | 3、8、2 | 2 が |
Python
def two_sum(nums, target):
seen = {}
for i, x in enumerate(nums):
need = target - x
if need in seen:
return [seen[need], i]
seen[x] = i
print(*two_sum([3, 8, 2, 7], 9))JavaScript
function twoSum(nums, target) {
const seen = new Map();
for (let i = 0; i < nums.length; i++) {
const need = target - nums[i];
if (seen.has(need)) {
return [seen.get(need), i];
}
seen.set(nums[i], i);
}
}
console.log(...twoSum([3, 8, 2, 7], 9));実行した出力
2 3要点 ハッシュマップは、
面接での一言
動きで見る
4. ソートと 二分探索 (並べて 半分ずつ絞る)
たとえ 辞書は
数列 2、
| 手 | 範囲 | 真ん中の値 | 判断 |
|---|---|---|---|
| 1 | 0 から 9 | 4 番の 16 | 23 より |
| 2 | 5 から 9 | 7 番の 56 | 23 より |
| 3 | 5 から 6 | 5 番の 23 | 見つかった。 |
Python
def search(nums, t):
lo, hi = 0, len(nums) - 1
while lo <= hi:
mid = (lo + hi) // 2
if nums[mid] == t:
return mid
if nums[mid] < t:
lo = mid + 1
else:
hi = mid - 1
return -1
nums = [
2, 5, 8, 12, 16,
23, 38, 56, 72, 91,
]
print(search(nums, 23))
rest = sorted([10, 9, 1])
print(*rest)JavaScript
function search(nums, t) {
let lo = 0;
let hi = nums.length - 1;
while (lo <= hi) {
const mid = Math.floor((lo + hi) / 2);
if (nums[mid] === t) return mid;
if (nums[mid] < t) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
const nums = [
2, 5, 8, 12, 16,
23, 38, 56, 72, 91,
];
console.log(search(nums, 23));
const rest = [10, 9, 1];
rest.sort((a, b) => a - b);
console.log(...rest);実行した出力
5
1 9 10要点 毎回
面接での一言
重複が
| 形 | 範囲の持ち方 | 向く問題 |
|---|---|---|
| 閉じた | lo と hi の | 値が |
| 半開の | lo は | 左端、 |
mid は lo + (hi - lo) / 2 と
Python
def lower(nums, t):
lo, hi = 0, len(nums)
while lo < hi:
mid = lo + (hi - lo) // 2
if nums[mid] < t:
lo = mid + 1
else:
hi = mid
return lo
nums = [1, 2, 2, 2, 3, 5]
first = lower(nums, 2)
count = lower(nums, 3) - first
print(first, count)
print(lower(nums, 4))JavaScript
function lower(nums, t) {
let lo = 0;
let hi = nums.length;
while (lo < hi) {
const half = Math.floor((hi - lo) / 2);
const mid = lo + half;
if (nums[mid] < t) lo = mid + 1;
else hi = mid;
}
return lo;
}
const nums = [1, 2, 2, 2, 3, 5];
const first = lower(nums, 2);
const count = lower(nums, 3) - first;
console.log(first, count);
console.log(lower(nums, 4));実行した出力
1 3
52 の
二分探索は、
Python
def smallest_root(n):
lo, hi = 0, n
while lo < hi:
mid = lo + (hi - lo) // 2
if mid * mid >= n:
hi = mid
else:
lo = mid + 1
return lo
print(smallest_root(1000))
print(smallest_root(1024))JavaScript
function smallestRoot(n) {
let lo = 0;
let hi = n;
while (lo < hi) {
const half = Math.floor((hi - lo) / 2);
const mid = lo + half;
if (mid * mid >= n) hi = mid;
else lo = mid + 1;
}
return lo;
}
console.log(smallestRoot(1000));
console.log(smallestRoot(1024));実行した出力
32
3231 の 2 乗は 961 で 1000 に
動きで見る
5. スタックと キュー (お皿と行列)
たとえ スタックは
| やること | Python | JavaScript |
|---|---|---|
| スタックに入れる | st.append(x) | st.push(x) |
| スタックから出す | st.pop() | st.pop() |
| キューに入れる | dq.append(x) | q.push(x) |
| キューから出す | dq.popleft() | q.shift() |
Python の
スタックの
| 手 | 文字 | すること | スタックの |
|---|---|---|---|
| 1 | ( | 積む | ( |
| 2 | { | 積む | ( { |
| 3 | [ | 積む | ( { [ |
| 4 | ] | 上の [ と | ( { |
| 5 | } | 上の { と | ( |
| 6 | ) | 上の ( と | 空 |
最後に
Python
def is_valid(s):
pairs = {
")": "(",
"]": "[",
"}": "{",
}
st = []
for ch in s:
if ch not in pairs:
st.append(ch)
elif not st:
return False
elif st.pop() != pairs[ch]:
return False
return not st
def show(ok):
print("ok" if ok else "ng")
show(is_valid("({[]})"))
show(is_valid("(]"))JavaScript
function isValid(s) {
const pairs = {
")": "(",
"]": "[",
"}": "{",
};
const st = [];
for (const ch of s) {
if (!(ch in pairs)) {
st.push(ch);
} else if (st.pop() !== pairs[ch]) {
return false;
}
}
return st.length === 0;
}
function show(ok) {
console.log(ok ? "ok" : "ng");
}
show(isValid("({[]})"));
show(isValid("(]"));実行した出力
ok
ng6. 再帰と 木 (自分を 呼ぶ関数と 枝分かれ)
たとえ 会社の
再帰を
次の
- 1 (根)
- 左の
子 2 - 左の子 4
- 右の子 3
- 左の
深さは、
| 呼ぶ点 | 左の深さ | 右の深さ | 戻り値 |
|---|---|---|---|
| 4 | 0 | 0 | 1 |
| 2 | 1 | 0 | 2 |
| 3 | 0 | 0 | 1 |
| 1 | 2 | 1 | 3 |
Python
class Node:
def __init__(self, v,
l=None, r=None):
self.v = v
self.l = l
self.r = r
def depth(node):
if node is None:
return 0
return 1 + max(depth(node.l),
depth(node.r))
left = Node(2, Node(4))
tree = Node(1, left, Node(3))
print(depth(tree))JavaScript
class Node {
constructor(v, l = null, r = null) {
this.v = v;
this.l = l;
this.r = r;
}
}
function depth(node) {
if (node === null) return 0;
return 1 + Math.max(depth(node.l),
depth(node.r));
}
const left = new Node(2, new Node(4));
const tree = new Node(1, left, new Node(3));
console.log(depth(tree));実行した出力
37. グラフ探索と 幅優先探索 (つながりをたどる)
たとえ SNS で、
点 A から E の 5 つが、
| 点 | つながり先 |
|---|---|
| A | B、C |
| B | A、D |
| C | A、D |
| D | B、C、E |
| E | D |
幅優先探索は、
| 手 | 取り出す点 | 行列の | Aからの距離 |
|---|---|---|---|
| 1 | A | B、C | A は 0 |
| 2 | B | C、D | B は 1 |
| 3 | C | D (D は | C は 1 |
| 4 | D | E | D は 2 |
| 5 | E | 空 | E は 3 |
2 つの
| 比べるところ | 幅優先 (BFS) | 深さ優先 (DFS) |
|---|---|---|
| 使う入れ物 | キュー | スタックか再帰 |
| たどる順 | 近い順 | 行き止まりまで進む |
| 向く問題 | 最短の | 行けるかの |
Python
from collections import deque
graph = {
"A": ["B", "C"],
"B": ["A", "D"],
"C": ["A", "D"],
"D": ["B", "C", "E"],
"E": ["D"],
}
def bfs(start):
dist = {start: 0}
queue = deque([start])
while queue:
u = queue.popleft()
for v in graph[u]:
if v in dist:
continue
dist[v] = dist[u] + 1
queue.append(v)
return dist
def dfs(u, seen):
seen[u] = True
for v in graph[u]:
if v not in seen:
dfs(v, seen)
return seen
dist = bfs("A")
print(" ".join(dist), dist["E"])
print(" ".join(dfs("A", {})))JavaScript
const graph = {
A: ["B", "C"],
B: ["A", "D"],
C: ["A", "D"],
D: ["B", "C", "E"],
E: ["D"],
};
function bfs(start) {
const dist = new Map([[start, 0]]);
const queue = [start];
let head = 0;
while (head < queue.length) {
const u = queue[head++];
for (const v of graph[u]) {
if (dist.has(v)) continue;
dist.set(v, dist.get(u) + 1);
queue.push(v);
}
}
return dist;
}
function dfs(u, seen) {
seen.add(u);
for (const v of graph[u]) {
if (!seen.has(v)) {
dfs(v, seen);
}
}
return seen;
}
const dist = bfs("A");
const order = [...dist.keys()];
console.log(order.join(" "), dist.get("E"));
const seen = dfs("A", new Set());
console.log([...seen].join(" "));実行した出力
A B C D E 3
A B D C E要点 見た
面接での一言
8. 動的計画法 (途中の 答えをメモ)
たとえ 階段を 1 段か 2 段ずつ登る
| 段の数 | 登り方の通り数 | 式 |
|---|---|---|
| 1 | 1 | 1 段だけ |
| 2 | 2 | 1 段 + 1 段、 |
| 3 | 3 | 2 段の 2 + 1 段の 1 |
| 4 | 5 | 3 段の 3 + 2 段の 2 |
| 5 | 8 | 4 段の 5 + 3 段の 3 |
| 6 | 13 | 5 段の 8 + 4 段の 5 |
動的計画法 (DP) の
Python
def climb(n):
dp = [1, 1]
for i in range(2, n + 1):
dp.append(dp[-1] + dp[-2])
return dp[n]
print(climb(6))JavaScript
function climb(n) {
const dp = [1, 1];
for (let i = 2; i <= n; i++) {
dp.push(dp[i - 1] + dp[i - 2]);
}
return dp[n];
}
console.log(climb(6));実行した出力
13メモの
Python
calls = [0, 0]
memo = {}
def plain(n):
calls[0] += 1
if n <= 1:
return 1
a = plain(n - 1)
return a + plain(n - 2)
def with_memo(n):
calls[1] += 1
if n <= 1:
return 1
if n not in memo:
a = with_memo(n - 1)
b = with_memo(n - 2)
memo[n] = a + b
return memo[n]
print(plain(25), with_memo(25))
print(*calls)JavaScript
const calls = [0, 0];
const memo = new Map();
function plain(n) {
calls[0] += 1;
if (n <= 1) return 1;
return plain(n - 1) + plain(n - 2);
}
function withMemo(n) {
calls[1] += 1;
if (n <= 1) return 1;
if (!memo.has(n)) {
const a = withMemo(n - 1);
const b = withMemo(n - 2);
memo.set(n, a + b);
}
return memo.get(n);
}
console.log(plain(25), withMemo(25));
console.log(...calls);実行した出力
121393 121393
242785 49要点 25 段の
面接での一言
よくある問い
計算量とは何ですか
入力の
O(n) と O(n²) は、 どれくらい 違いますか
n が 1,000 なら、
二分探索は、 なぜ O(log n) ですか
毎回、
幅優先探索と 深さ優先探索は、 どう 使い 分けますか
最短の
動的計画法と、 メモ付きの 再帰は 同じですか
考え方は
8 つの テーマは、 どの 順で 練習しますか
この
出典と確かめ方
文ゆめさく。
| 問題 | 手数の比 | 記憶の比 |
|---|---|---|
| Two Sum | 2.00 | 2.00 |
| Valid Parentheses | 2.00 | 2.00 |
| Binary Search | 1.07 | 記憶は増えず |
| Contains Duplicate | 2.00 | 2.00 |
| Valid Anagram | 2.00 | 1.00 |
| Reverse Linked List | 2.00 | 1.00 |
| Maximum Depth of Binary Tree | 2.00 | 1 本道は 2.00、 |
| Climbing Stairs | 2.00 | 1.00 |
| Best Time to Buy and Sell Stock | 2.00 | 1.00 |
| Valid Palindrome | 2.00 | 1.00 |
| Longest Substring Without Repeating Characters | 2.00 | 1.16 |
| Merge Two Sorted Lists | 2.00 | 1.00 |
| Number of Islands | 4.00 | 4.00 |
| Group Anagrams | 2.00 | 2.00 |
Number of Islands は、
出典は
- Python の
仕様は、 collections.deque と list の 計算量の表を 参照しました - 「まず
これだけは 解く 14 問」の 番号と 題は、 英語の 問題集の 公開の API (leetcode.com/graphql) で 2026 年 10 月 30 日に 取った 値です。 14 問とも、 無料の アカウントで 開ける ものでした - JavaScript の
仕様は、 MDN の Map と Array.prototype.sort を 参照しました
次の一歩
表を