E資格レベル:Pythonデータ構造 10本ノック(発展編)
Q11. リストの先頭要素削除の計算量
要素数 N のリスト my_list に対し、my_list.pop(0) を実行して先頭の要素を削除した場合の平均計算量(Big-O)として正しいものはどれか。
答えを見る
正解:C. O(N) (線形時間)
解説:リストはメモリ上で連続しているため、先頭の要素を削除すると、その後の要素すべてを一つずつ前にずらす(再配置する)必要があります。この操作回数は N に比例するため、計算量は O(N) です。末尾の削除(pop())は O(1) です。
Q12. 辞書とセットの最悪計算量(ハッシュ衝突)
ハッシュテーブル(辞書や集合の内部構造)におけるキーの検索(key in d や d[key])の最悪計算量として正しいものはどれか。
答えを見る
正解:C. O(N) (線形時間)
解説:通常は平均 O(1) ですが、**ハッシュ衝突**が発生し、すべてのキーが同じバケット(格納場所)に入ってしまった最悪のケースでは、目的のキーを見つけるためにすべての要素を順番に比較する必要が生じ、計算量は O(N) に悪化します。
Q13. タプルの生成効率
大量の要素 N を持つリストとタプルを生成する際、タプル生成のメモリおよび処理効率に関する記述として最も適切なものはどれか。
答えを見る
正解:A. タプルは不変なので、リストより生成速度とメモリ効率がわずかに高い。
解説:タプルはイミュータブルであるため、リストが必要とする「要素変更のための予約メモリ領域」が不要です。このため、タプルはリストよりも**コンパクト**であり、生成時のオーバーヘッドも少なく、わずかに効率的です。
Q14. ミュータブルなデフォルト引数
以下のコードを実行した際、list_a と list_b の出力として正しいものはどれか。
def add_to_list(element, data=[]):
data.append(element)
return data
list_a = add_to_list(1)
list_b = add_to_list(2)
答えを見る
正解:B. list_a: [1], list_b: [1, 2]
解説:デフォルト引数の data=[] は、関数が定義されたときに**一度だけ評価**されます。リストはミュータブル(可変)なため、2回目の呼び出しで list_a が使用したのと同じリストオブジェクトが再利用され、要素が追加されます。この挙動を避けるには、data=None をデフォルト値とし、関数内で if data is None: data = [] と初期化します。
Q16. for ループ中のリスト変更
以下のコードが無限ループ(または非常に長いループ)に陥る理由を説明する最も適切なものはどれか。
a = [1, 2, 3]
for x in a:
if x % 2 != 0:
a.append(x)
答えを見る
正解:B. ループ中に要素が末尾に追加され、リストのサイズが常に大きくなるため、ループの終端に到達しない。
解説:for ループがリストの要素を反復処理している間に、append() によってリストの末尾が伸び続けるため、イテレータが終端にたどり着くことができず、実質的に無限ループとなります。ループ中にリストを変更する際は、元のリストのコピー(a[:]など)に対してループを実行すべきです。
Q17. 集合への複合データ型の追加
集合 s = {1, 2} に、リスト [3, 4] とタプル (5, 6) を追加しようとしたとき、エラーになる操作はどれか。
答えを見る
正解:C. s.add([3, 4])
解説:集合の要素も辞書のキーと同じく**ハッシュ可能(Hashable)**である必要があります。リスト([])はミュータブル(可変)なためハッシュを持てず、追加しようとすると TypeError が発生します。タプル(())は不変なので追加可能です。
Q18. ジェネレータの消費(一度きりのアクセス)
以下のコードを実行した後、再度 for x in x: を実行しようとした場合の結果として正しいものはどれか。
x = (i for i in range(5)) # ジェネレータ式
# 最初の消費
for i in x:
pass
# 2回目のループ
for x in x:
print(x)
答えを見る
正解:C. 何も出力されず、ループが即座に終了する。
解説:ジェネレータは**一度しか反復処理できない(消費される)**イテレータです。最初のループで全ての値が生成・消費された後、ジェネレータは空になります。2回目のループでは、ジェネレータはすぐに終端を検知し、ループが実行されることなく終了します。
Q19. 辞書の pop() メソッドとデフォルト値
辞書 d = {'a': 1, 'b': 2} からキー 'c' の要素を**削除**しようとした際、エラーを出さずに 0 を返したい。以下のコードで目的を達成できるものはどれか。
答えを見る
正解:A. d.pop('c', 0)
解説:pop() メソッドは、キーが存在しない場合に備えて、第二引数に**デフォルト値**を指定できます。このデフォルト値は、キーが見つからなかったときにエラーの代わりに返されます。Dの get() は削除機能がありません。
Q20. 集合の差集合の非対称性
集合 A = {1, 2, 3} と B = {3, 4, 5} について、`A - B` と `B - A` の実行結果として正しいものはどれか。
答えを見る
正解:B. A - B: {1, 2}, B - A: {4, 5}
解説:差集合(- 演算子)は、**非対称**な演算です。A - B は「AにあってBにないもの」、B - A は「BにあってAにないもの」を意味します。