Pythonでリストからn番目に大きい要素を線形時間で選択するプログラム
リストから線形時間計算量 O(n) で n 番目に大きい要素を選択するには、主に2つの処理が必要になります。
- ピボットを基準にリストを2つの部分に分割する「パーティション」処理
- 分割された部分の中から目的の要素を再帰的に絞り込んでいく「選択」処理
この手法は、クイックソートの考え方を応用した Quickselect(クイックセレクト)アルゴリズム として知られています。ユーザーが指定した「i」の値に基づいてリストを分割し、そのたびに探索範囲を半分以下に狭めていくことで、全体をソートせずに効率よく目的の要素を見つけられます。
サンプルコード
def select_largest(my_list, beg, end, i):
if end - beg <= 1:
return my_list[beg]
pivot_val = start_partition(my_list, beg, end)
k = end - pivot_val
if i < k:
return select_largest(my_list, pivot_val + 1, end, i)
elif i > k:
return select_largest(my_list, beg, pivot_val, i - k)
return my_list[pivot_val]
def start_partition(my_list, beg, end):
pivot_val = my_list[beg]
i = beg + 1
j = end - 1
while True:
while (i <= j and my_list[i] <= pivot_val):
i = i + 1
while (i <= j and my_list[j] >= pivot_val):
j = j - 1
if i <= j:
my_list[i], my_list[j] = my_list[j], my_list[i]
else:
my_list[beg], my_list[j] = my_list[j], my_list[beg]
return j
my_list = input('Enter the list of numbers.. ')
my_list = my_list.split()
my_list = [int(x) for x in my_list]
i = int(input('Enter the value for i.. '))
ith_largest = select_largest(my_list, 0, len(my_list), i)
print('The result is {}.'.format(ith_largest))実行結果
Enter the list of numbers.. 34 67 12 0 999 Enter the value for i.. 1 The result is 999.
コードの解説
select_largestメソッドが定義され、リスト・開始インデックス・終了インデックス・「i」の値を引数として受け取ります。start_partitionメソッドが定義され、ピボット値を基準にリストを2つの部分に分割します。パーティション処理は
select_largestの内部から呼び出されます。select_largestは自分自身を再度呼び出しています。これが再帰処理による実装です。数値のリストはユーザーからの入力として受け取ります。
split()によって入力文字列が空白区切りで分割されます。リスト内包表記により、各要素が整数へと変換されます。
「i」の値もユーザーから入力として受け取ります。
この「i」の値に基づき、リストが2つの部分に振り分けられます。
目的の要素が存在する側の部分リストに対してのみ
select_largestを再帰的に適用し、不要な側は捨てることで計算量を抑えています。最終的な結果がコンソールに出力されます。
計算量について
平均的なケースでは、各再帰ステップで探索対象が半分程度に減っていくため、O(n) + O(n/2) + O(n/4) + … = O(2n) ≒ O(n) となり、線形時間での選択が可能です。ただし、ピボットの選び方が不運な場合(最悪ケース)には O(n²) まで悪化する可能性がある点には注意が必要です。
-
Pythonで配列内の最大の要素を見つける方法を解説
この記事では、「配列の中から最大の要素を求める」という問題の解決方法について詳しく解説します。 問題の概要 問題文:与えられた配列に対して、その中で最も大きい要素を計算して求める必要があります。 ここではブルートフォース(総当たり)アプローチを使用します。これは、配列全体を先頭から順番に走査しながら各要素を比較し、その時点での最大値を更新していくというシンプルかつ確実な手法です。 実装例 以下に具体的なコードを示します。 # 最大値を求める関数 def largest(arr, n): # 最大要素の初期値として最初の要素を設定 max = arr[0] # 配列全体を
-
Pythonでリスト内の最大値を持つ要素を見つける方法
Pythonのリストから最大値を持つ要素を見つけるには、組み込み関数 max() にリストを引数として渡すだけです。max() 関数はリストを先頭から順に走査し、それまでに見つけた最大値を記録しながら末尾まで進み、最終的にその最大値を返します。基本的な使い方以下は、リスト内の最大値を取得するシンプルな例です。my_list = [2, 3, 1, 5, -1] print(max(my_list))出力結果このコードを実行すると、次のように最大値が出力されます。5最大値のインデックス(出現位置)も取得する方法最大値そのものだけでなく、リスト内で最大値が出現するすべての位置(インデックス)を知り