Pythonで最も視聴された上位K番組の合計視聴時間を求めるプログラム
文字列のリスト shows、整数のリスト durations、そして値 k が与えられたとします。shows[i] と durations[i] は、i 番目の人が視聴した番組名とその視聴時間を表しています。このとき、最も視聴された上位 k 件の番組について、合計視聴時間を求めるのがこの問題の目的です。
例えば、入力が次のような場合を考えてみましょう。
- shows = ["The BGT", "Jack jumper", "The BGT", "Jokers Company", "Music magic"]
- durations = [10, 8, 10, 18, 9]
- k = 2
この場合の出力は 38 になります。最も視聴された上位2つの番組は「Jokers Company」(18分)と「The BGT」(10 + 10 = 20分)であり、18 + 20 = 38 となるためです。
解決のアプローチ
この問題は、次の手順で解くことができます。
showsまたはdurationsが空、あるいはkが 0 の場合は 0 を返す- 空の辞書
d(defaultdict)を用意する - i を 0 から shows の要素数までループし、
d[shows[i]]にdurations[i]を加算して、番組ごとの視聴時間を集計する - 新しいリスト
lを作成し、辞書dの各値(番組ごとの合計視聴時間)を追加する - リスト
lを降順にソートする - i と answer を 0 に初期化し、i < k の間、answer に
l[i]を加算していく - answer を返す
実装例
理解を深めるために、以下の実装例を見てみましょう。
from collections import defaultdict
def solve(shows, durations, k):
if not shows or not durations or not k:
return 0
d = defaultdict(int)
for i in range(len(shows)):
d[shows[i]] += durations[i]
l = []
for i in d:
l.append(d[i])
l.sort(reverse=True)
i = 0
answer = 0
while i < k:
answer += l[i]
i += 1
return answer
shows = ["The BGT", "Jack jumper", "The BGT", "Jokers Company",
"Music magic"]
durations = [10, 8, 10, 18, 9]
k = 2
print(solve(shows, durations, k))
入力
["The BGT", "Jack jumper", "The BGT", "Jokers Company", "Music magic"], [10, 8, 10, 18, 9], 2
出力
38
計算量について
このアルゴリズムの時間計算量は O(n log n) です(n はレコードの総数)。すべての視聴記録を集計するのに O(n)、ソートに O(n log n) かかるためです。空間計算量は O(m)(m はユニークな番組数)で、辞書とリストに必要なメモリを格納します。
より簡潔な実装例(Counter を活用)
Python の標準ライブラリ Collections.Counter を使うと、同じ処理をより簡潔に書くこともできます。
from collections import Counter
def solve(shows, durations, k):
counter = Counter()
for show, duration in zip(shows, durations):
counter[show] += duration
return sum(sorted(counter.values(), reverse=True)[:k])
zip() を使うことで番組名と視聴時間をペアで処理でき、コードの可読性が向上します。また、heapq.nlargest(k, counter.values()) を使えば、全要素をソートせずに上位 k 件だけを効率的に取得することも可能です。
-
Pythonで循環トラック上のレースにおける最も訪問されたセクターを見つける方法
数字 n と配列 rounds があるとします。ここで、1 から n までの番号が付けられた n 個の異なるセクターで構成される円形トラックを考えます。このトラックでレースが開催され、レースは m ラウンドで構成されています。i 番目のラウンドはセクター rounds[i - 1] から開始し、セクター rounds[i] で終了します。たとえば、第 1 ラウンドはセクター rounds[0] から始まり、rounds[1] で終わります。 私たちのタスクは、最も多く訪問されたセクターを昇順で求めることです。(トラックの番号は反時計回りの方向でセクター番号の昇順に配置されているものとします)
-
Pythonですべての出荷を完了するために必要な総コストを求めるプログラム
リストのリスト ports が与えられているとします。ここで ports[i] は、港 i が接続されている港の一覧を表します。さらに別のリストのリスト shipments もあり、その各要素は [i, j] という形式のシーケンスで、「港 i から港 j への出荷依頼」を意味します。港 i から港 j へ出荷するコストは、2つの港間の最短経路の長さとして定義されます。このとき、すべての出荷を完了させるために必要な総コストを求めるのが課題です。たとえば、入力が次のような場合を考えてみましょう。ports = [[1, 4],[2],[3],[0, 1],[]] shipments = [[1,