コーディング面接で使われる構文、データ構造、標準関数などは実はある程度限定されています。ここに書いてある事を理解するだけでコーディング面接における(体感)8 ~ 9割くらいのPythonの必要な知識を学習できます。
例えば、辞書やセットは頻繁に活用しますが、ジェネレーター・デコレータなどはコーディング面接ではそこまで登場しません。つまり必要なものだけ集中して学習し、残りの要素はその都度調べる形が効率良いでしょう。コーディング面接では万が一忘れた時は相手が自分の代わりにググってくれたり、擬似コードとして書くことも許される場合があります。
ここでは詳しいデータ構造やアルゴリズムの知識の話はせず、Pythonの構文やデータ構造の使い方にのみフォーカスをして話していきます。
変数(Variable)
Pythonは動的型付け言語で、変数を宣言するときにその型を明示する必要はありません。したがって、
n = 0
といった宣言を行うときに、型は指定されません。変数の型は実行時に決定されるため、同一の変数に違う型の値を再代入することが可能です。複数の変数を一行で代入することも可能です。例えば、
a, b = 1, 2
といった形で代入を行います。2つの変数をスワップ(交換)もPythonでは
a, b = b, a
と書くことで簡単にできるようになっています。複数の変数に一括で同じ値を代入する事もできます。
n += 1
およびn -= 1
は、インクリメント(加算)とデクリメント(減算)を表しています。例えば、Javaのようにn++
とは書けないので注意しましょう。Pythonでは
None
はNull値を表し、変数が何も値を持たないことを示します。これは変数が初期化されたがまだ値が割り当てられていない、または明示的にその変数の値を消去したい場合などに使用されます。If文(if statement)
Pythonのif文は他の言語と比べて独特な書き方をしています。Pythonでは、if文を書く際に条件式を括弧で囲む必要はありません。また、ブロックを表現するためにはカーリーブラケット(
{}
)ではなく、インデント(通常はスペース4つ)を使用します。また、else if
の代わりにelif
を使用します。Pythonでは
and
、or
、not
ブール演算子です。これらは、真偽値(True
またはFalse
)を持つ式の評価に用いられます。例えば、n > 0 and m > 0
の場合、n
とm
が共に0より大きい場合はTrue
を返し、そうでなければFalse
を返します。Pythonでは行末にバックスラッシュ(
\
)をつけるか、括弧(()
)内に条件式を記述することで条件式を複数行に分割できます。while文(while statement)
- Pythonの
while
文は、条件が真(True
)である限り繰り返し処理(ループ)を実行します。そのため、while文のブロック内のコードは、指定した条件が偽(False
)になるまで何度でも実行されます。
while文の中に
break
文を記述することで、条件が真である場合でも強制的にループを抜け出すことが可能です。また、continue
文を使うと、ループの残りの部分をスキップして次のイテレーションに移行します。for文(for statement)
Pythonでは、for文を使用してシーケンス(リストや文字列など)を繰り返すことができます。特定の回数だけ繰り返すためには
range()
関数を用います。例えば、for i in range(5):
は0から4までのシーケンスを作成し5回の繰り返し処理を行います。なお、rangeは厳密にはクラスだが、組み込み関数の一種として呼ばれているのでここでは関数と呼びます。range()
関数には2つまたは3つの引数を渡すことも可能で、それぞれ開始値、終了値、ステップ数を指定することができます。例えば、for i in range(2, 5):
は2から4まで繰り返し、for i in range(5, 1, -1):
は5から2まで逆順に繰り返します。また、revsersed
を使って逆順に繰り返し処理を行う事もできます。Pythonのfor文でも、
break
とcontinue
のキーワードを使用することができます。また、
for
文のelse
ブロックは抑えておきたい特徴の一つです。これはfor
ループが完全に終了した後に実行されるブロックです。ただし、break
文によってループが途中で終了した場合は、else
ブロックは実行されません。Math
Pythonでは、様々な数学的な演算が可能です。例えば、
/
演算子を使うと、浮動小数点数による除算ができます。一方、//
演算子を使うと、整数による除算(切り捨て除算)ができます。負の数に対して//
を使うと、結果は小数点以下を切り捨てて整数にします。また、
%
演算子を使うと、剰余(余り)を計算できます。負の数に対する剰余計算では、Pythonは負の値を返さず、代わりに剰余に最も近い非負の値を返します。しかし、math.fmod()
関数を使うと、剰余計算で負の数が正確に扱われます。つまり、第一引数が負の場合、結果も負となりま doす。Pythonのmathモジュールには、他にも多くの数学関数が含まれています。
math.floor()
関数は引数以下の最大の整数を、math.ceil()
関数は引数以上の最小の整数をそれぞれ返します。math.sqrt()
関数は平方根を、math.pow()
関数はべき乗を計算します。また、**
演算子もべき乗を計算します。Pythonには無限大を表現するための特殊な値があり、
float("inf")
とfloat("-inf")
を使って正の無限大と負の無限大を作成できます。これらの値は、他の浮動小数点数と同様に演算できます。たとえば、非常に大きな数を計算してもオーバーフローすることなく、無限大と比較することができます。配列(Array)
Pythonには配列として機能する組み込みのデータ型がいくつかありますが、最も一般的に使用されるのは
list
型です。リストは[]
で定義され、その中に任意の数と種類の要素を含めることができます。例えば、numbers = [1, 2, 3, 4, 5]
は整数のリストであり、strings = ["hello", "world"]
は文字列のリストです。リストには
len()
関数を用いる事で長さを取得できます。リストの要素にはインデックス(0から始まる)でアクセスします。負のインデックスを指定すると、リストの終端から逆方向に要素を参照できます。
スライス機能は配列から一部の要素を取り出すための機能です。
numbers[1:4]
は2番目から4番目までの要素を取得します。Pythonのリストは動的であり、
append()
を用いて新たな要素をリストの終端に追加することができます。pop()
を使うとリストの終端の要素を削除します。insert()
を使うと特定の位置に新たな要素を挿入することができます。次章以降で詳しく解説しますが、Pythonのリストは動的配列で実装されておりinsert()
はO(N)の時間計算量となり非効率なので使う場合には注意しなければなりません。また、
in
演算子を用いて、特定の要素がリストに含まれているかどうかを調べることができます。この演算子は、指定した要素がリスト内に存在すればTrue
を、存在しなければFalse
を返します。しかし先頭から要素を線形探索する事になるので、こちらも時間計算量的には非効率的です。また配列が空判定するときにはlen関数を使わずに以下のように書く事もできます。
文字列(String)
Pythonの文字列はシングルクォート(
'
)またはダブルクォート("
)で囲むことで定義します。例えば、s = 'hello'
またはs = "hello"
のように記述します。文字列の要素にはインデックスでアクセスします。文字列には
len()
関数を用いる事で長さを取得できます。文字列を結合するには
+
演算子を使用します。またフォーマット済み文字列リテラル(f-string)を使う事もできます。配列と同じように、スライス機能を使用して、文字列の一部を取り出すことができます。例えば、
s[0:2]
は文字列sの1番目から2番目の要素を取得します。文字列はイミュータブル(変更不能)なので、一度定義した文字列の要素を直接変更することはできません。例えば、
s[0] = "H"
のようなコードは例外を引き起こします。int()
関数を使用して、文字列を整数に変換することができます。また、str()
関数を使用して、数値を文字列に変換することができます。ord()
関数を使用して、文字列を対応するASCIIコードに変換することができます。例えば、ord("a")
は97を返し、ord("b")
は98を返します。この機能は、例えば小文字の英字の位置関係を調べる際に役立ちます。join()
メソッドを使用して、複数の文字列を一つの文字列に結合することができます。split()
メソッドを使用して、文字列を特定の区切り文字に基づいて複数の部分に分割することができます。これは、特定の文字で区切られたデータを個別の要素に分解する際に便利です。リスト内包表記(List comprehension)
Pythonのリスト内包表記は、リストを生成するコードをより短く、より読みやすくするための方法です。例えば、0から9までのすべての数字の平方を含むリストを作るには、通常のforループを使用するよりもリスト内包表記を使用した方がコードは短くなります。
他のプログラミング言語にはなかなかない機能ですが、例えば、JavaScriptの
map
やfilter
などと同じような使い方ができると思って問題ないと思います。2次元配列(2d array)
Pythonのリストを使用すると、多次元配列(例えば、2次元配列)も作成できます。2次元配列は「配列の配列」と考えることができ、行列などを表現するのに使われます。リスト内包表記を使うと、指定したサイズの2次元配列を簡単に作成することができます。以下に3x3の2次元配列を生成する例を示します。
しかし、次のように
*
演算子を使用して直接リストを複製すると、すべての内側のリストが同じ参照(つまり同じオブジェクト)を指すことになります。そのため、一つの内側のリストを変更すると、他のすべての内側のリストも同様に変更されてしまいます。このため、2次元配列を作成する際にはこの方法を避けるべきです。キュー(Queue)
Pythonの
collections
モジュールのdeque
クラスは、効率的な先入れ先出し(FIFO)データ構造(キュー)を提供します。要素をキューの最後(右側)に追加するには、append
メソッドを使用します。キューの先頭(左側)から要素を取り出すには、popleft
メソッドを使用します。なお、Pythonの
deque
クラスは双方向リストで実装されており、スタック(LIFO)としての機能も備えていますが、こちらは普通にPythonのリスト(配列)を用いてもほぼ同様の時間計算量を期待できるため、あえてこちらを使う必要はありません。deque
クラスの詳しい実装内容は次章以降で説明します。セット(Set)
Pythonのセット(
set
)は重複する要素を許さないコレクションです。新しい要素を追加するにはadd()
メソッドを使用します。要素がセットに存在するかどうかを確認するには、
in
キーワードを使用します。これは時間的計算量がO(1)であるため、要素の存在確認には非常に効率的です。セットから要素を削除するには、
remove()
メソッドを使用します。このメソッドは指定した要素がセットに存在しない場合、例外が投げられます。リストと同様にセット内包表記を使用することができます。これにより、ある範囲や条件に基づく要素を含むセットを簡単に生成することができます。
辞書(Dict - HashTable)
Pythonの辞書(
dict
)はハッシュテーブルとして機能します。キーと値のペアを保存することができ、キーを使用して値を迅速に取得することができます。辞書型は {}
を用いて定義され、以下のように要素を追加したり、既存の要素の値を更新したりできます。また、Pythonの辞書はキーを指定してその存在を確認することも可能です。これは
in
演算子を使うことで行うことができます。pop()
メソッドを使うと、指定したキーの要素を削除することができます。また、リストと同様に辞書内包表記を用いることで、より複雑なハッシュテーブルを生成することもできます。
辞書型の要素は、
keys()
、values()
、items()
メソッドを使って取得できます。これらのメソッドを使用して辞書型のキーだけ、値だけ、またはキーと値のペアを取得することができます。Pythonでは、標準の
dict
の他に、collections
モジュールのdefaultdict
を利用することができます。defaultdict
は、キーが存在しない場合にデフォルトの値を生成する機能があります。これにより、キーが未定義である場合にエラーを防いだり、初期化の手間を省くことができます。Counter
クラスも非常に便利なので覚えておきましょう。これは辞書のサブクラスで、ハッシュ可能なオブジェクトを数えるのに特化しています。Counter
オブジェクトは、要素をキーとして、その要素の出現回数を値として保持します。これにより、要素のカウントを効率的に行うことができます。タプル(Tuple)
Pythonのタプルは、一度作成したら変更できない(イミュータブルな)シーケンス型です。タプルは通常、異なるタイプの項目をグループ化するために使用されます。タプルはカンマで区切られた値の並びで、オプションで丸括弧
()
で囲まれます。タプルのはイミュータブルで、一度タプルが作成されると、その要素を変更することはできません。
タプルは辞書のキーとして使用したり、ハッシュセットの要素としても使用できます。一方、リストは辞書のキーとして使用することはできません。
ヒープ(Heap)
Pythonの
heapq
モジュールを使うと、リストを効率的にヒープとして扱うことができます。ヒープは、データ構造の一つで、特定の順序(通常は大小)でデータを保存します。このモジュールは最小ヒープを実装します。つまり、ヒープの最小の要素が常にルート、すなわち、インデックス0に存在します。一方、Pythonの
heapq
モジュールには最大ヒープを直接実装する機能はありません。しかし、値をネガティブにすることで最大ヒープを実現できます。つまり、ヒープに値を追加するときにはマイナス記号をつけて、ヒープから値を取り出すときにはマイナス記号を再度つけて値を元に戻します。heapq.heapify()
関数を使用すると、既存のリストをその場でヒープの形に変更することができます。ソート(Sorting)
Pythonの
sorted()
関数を使うと、リストをソートすることができます。この関数は新しいソート済みリストを返すため、元のリストは変更されません。なおデフォルトでは昇順でソートされます。sort()
メソッドはリスト自体を破壊的にソートします(元の配列が書き換えられる)。また、sort()
メソッドには引数があり、これを使用するとソートの順序を逆にすることができます。降順でソートするには、reverse=True
を引数として指定します。文字列を含むリストもソートすることができます。デフォルトでは、辞書順(正確にはASCIIコード順)でソートされます。
sort()
メソッドのkey
引数を使用すると、ソートの基準をカスタマイズすることができます。例えば、リストの要素(文字列)を長さでソートするためには、key
引数に長さを返す関数を指定します。また、
tuple
は複数の要素でソートする時にとても便利なので覚えましょう。tuple
の最初の要素から順に比較していきソートされます。例えば、出現回数順 -> 辞書順でソートしたい時になどに使える手法になります。ちなみにtuple
の代わりにlist
を使っても同様の結果が得られます。優先度付きキュー(heapq
)などでも同様に評価されるので覚えておきましょう。なお、もちろん複数の要素をソートする際には先程紹介したkey
引数を使う事もできます。関数(Function)
Pythonでは、defキーワードを使用して関数を定義します。
内部関数(Inner Function)
Pythonでは、関数の内部に別の関数を定義することができます。これを内部関数またはネストした関数と言います。また内部関数から外部関数の変数にアクセスする事ができます。
Pythonの
nonlocal
キーワードは、ネストした関数(内部関数)から外部関数(親関数)のローカル変数を参照または変更するために使用します。以下に一例を示します。またミュータブルな変数(リストや辞書等)だとオブジェクトが参照によって渡されるためnonlocal
を使う必要ありません。クラス(Class)
Pythonのクラスは以下のように定義します。Pythonのコンストラクタは
__init__
メソッドで、これはクラスからインスタンスを作成する際に自動的に呼び出されます。この__init__
メソッドを通じて、新しく作成されたインスタンスの初期設定が行われます。また、クラス内で定義された関数をインスタンスメソッドと呼びます。メソッドの最初の引数は通常self
と名付けられ、これがそのメソッドを呼び出したインスタンス自体を指します。なお、一般的にLeetCode形式のコーディング面接では必要最小限のクラスの構文をまず優先的に覚える事をオススメしています。殆どの問題は関数実装で終わりますが、クラス全体の設計をするパターンもあるからです。最悪忘れたら面接官に「ここは疑似コードです」と言いましょう。私は過去に継承の方法が他のプログラミング言語と混同して忘れてしまい、面接官に確認した事があります。その時は面接官の方が優しかったので代わりにググって教えてくれました。
bisect
Pythonの
bisect
モジュールは、ソートされたリストに対して効率的な二分探索が可能となります。Sorted Containers
はじめにSorted ContainersはPythonの標準ライブラリではありません。C++ではstd::multisetなどに相当する機能を使うことができます。例えばSorted Containersの中にあるSortedListクラスの説明をします。コーディングテストの問題では既にソートされた配列に新しい要素をソート順を維持しながら追加する事が必要な問題があったとします。普通であればO(N)の時間計算量がかかりますが、SortedListではO(logN)で挿入する事ができます。
Pythonの標準ライブラリではありませんが、基本的にコーディング面接では言語における差は重要ではなくさらにエディタに書くだけで実行しないパターンもあるため、面接官と交渉して使えるかを確認しましょう。
ライブラリのインストールは↓
Sorted Containersの使い方