Pythonで完了できるタスク数を求めるプログラムの書き方
問題の概要
タスクのリストと人のリストが与えられたとします。tasks[i] は i 番目のタスクを実行するために必要な体力(強さ)を表し、people[i] は i 番目の人が持っている体力を表します。ここで、「1人は最大でも1つのタスクしか担当できない」という条件のもとで、完了できるタスクの総数を求める必要があります。
例えば、入力が tasks = [4, 3, 9, 15]、people = [10, 5, 3, 2] の場合、出力は 3 になります。これは、1人目がタスク「9」を、2人目がタスク「4」を、3人目がタスク「3」をそれぞれ実行でき、4人目はどのタスクも実行できないためです。
解決のアプローチ
この問題は、両方のリストをあらかじめ昇順にソートしてから、貪欲法(グリーディ法)の要領で「最も弱い人から、まだ割り当てられていない最も軽いタスク」へ順にマッチングさせていくことで解けます。以下の手順に従います。
- リスト
tasksを昇順にソートし、リストpeopleも昇順にソートする - カウンター
ctとインデックスindをそれぞれ 0 で初期化する - i を 0 から people のサイズまで繰り返す
- j を ind から tasks のサイズまで繰り返す
people[i] >= tasks[j]であれば、ctを 1 増やし、indを 1 増やして内側のループを抜ける- そうでなければ、その時点でループを抜ける
- j を ind から tasks のサイズまで繰り返す
- 最後に
ctを返す
このアルゴリズムでは、ソート済みのリストに対して各人が一度だけ走査されるため、計算量はソート部分が O(n log n)、マッチング部分が O(n + m) となり、非常に効率的です。
実装例
理解を深めるために、以下の実装を見てみましょう。
class Solution: def solve(self, tasks, people): tasks.sort() people.sort() ct = 0 ind = 0 for i in range(len(people)): for j in range(ind, len(tasks)): if people[i] >= tasks[j]: ct += 1 ind += 1 break else: break return ct ob = Solution() tasks = [4, 3, 9, 15] people = [10, 5, 3, 2] print(ob.solve(tasks, people))
入力
[4, 3, 9, 15], [10, 5, 3, 2]
出力
3
-
Pythonで整数の2進表現に含まれる1のビット数を数える方法
ある整数 n が与えられたとき、その数を2進数で表した際に含まれる「1」のビット(セットビット)の個数を求めることを考えます。この問題は「ポピュレーションカウント」や「ハミング重み」と呼ばれることもあり、ビット演算の基礎を学ぶのに最適な題材です。問題の例例えば、入力が 12 の場合を考えてみましょう。12 を2進数で表すと 1100 となり、「1」のビットは2個含まれています。したがって、出力は 2 になります。解法のアプローチこの問題は、次の手順で解くことができます。カウンター変数 count を 0 で初期化するn が 0 になるまで以下を繰り返すn の最下位ビット(n AND 1)を c
-
Pythonでグリッド上に集められるコインの最大数を求めるプログラム
問題の概要各セルにコインが置かれた2次元行列(マトリックス)があるとします。左上の [0,0] の位置からスタートし、右または下にのみ移動できるという制約のもとで、右下隅まで移動する過程で収集できるコインの最大数を求めるのがこの問題です。例として、次のような入力が与えられた場合を考えてみましょう。14226005この場合、出力は 14 になります。これは、パス [1, 4, 2, 2, 5] を通ることで、合計14枚のコインを集められるためです。解き方(動的計画法)この問題は動的計画法(DP)を使うと効率的に解けます。考え方はシンプルで、「あるセルに到達した時点でのコインの最大累積数」は、「そ