Pythonのcollections.Counterは、競技プログラミングで利用できる強力なツールです。以下のようなパターンでよく使用されます。
要素の頻度計算
与えられた配列や文字列内で、各要素の出現回数を簡単にカウントできます。
例題:
配列内で最も頻度が高い要素を見つける。重複した要素を探す。
from collections import Counter
arr = [1, 2, 2, 3, 3, 3, 4]
counter = Counter(arr)
most_common = counter.most_common(1)[0] # [(要素, 出現回数)]のリスト
print(most_common) # 出力: (3, 3)
アナグラム判定
2つの文字列がアナグラム(文字の並べ替えで一致)かどうかを確認します。
例題:
入力された2つの文字列がアナグラムかどうかを判定。
from collections import Counter
s1 = "listen"
s2 = "silent"
if Counter(s1) == Counter(s2):
print("アナグラム")
else:
print("アナグラムではない")
条件付きの頻度チェック
一定の条件を満たす頻度の要素を抽出するパターン。
例題:
配列内でk回以上出現する要素を抽出。
from collections import Counter
arr = [1, 1, 2, 2, 2, 3, 4, 4, 5]
k = 2
counter = Counter(arr)
result = [key for key, count in counter.items() if count >= k]
print(result) # 出力: [1, 2, 4]
多重集合の操作
複数のリストの要素間で和・積・差を計算できます。
例題:
2つのリストの共通部分や差分を求めるパターン。
from collections import Counter
list1 = [1, 2, 2, 3]
list2 = [2, 3, 3, 4]
counter1 = Counter(list1)
counter2 = Counter(list2)
# 共通部分
intersection = counter1 & counter2
print(list(intersection.elements())) # 出力: [2, 3]
# 差分
difference = counter1 - counter2
print(list(difference.elements())) # 出力: [1, 2]
頻度のカウントで分類
出現回数に基づいて要素をグループ化するパターン。
例題:
要素を頻度ごとに分類。
from collections import Counter
arr = [1, 1, 2, 2, 2, 3, 4, 4]
counter = Counter(arr)
grouped = {freq: [key for key, count in counter.items() if count == freq] for freq in set(counter.values())}
print(grouped) # 出力: {2: [1, 4], 3: [2], 1: [3]}
スライディングウィンドウでの使用
ウィンドウ内の要素頻度を動的に管理するパターン。
例題:
部分配列内の要素頻度を効率的にカウント。
from collections import Counter
arr = [1, 2, 2, 3, 3, 3, 4]
k = 3
window_counter = Counter(arr[:k])
print(window_counter) # 最初のウィンドウの頻度
for i in range(k, len(arr)):
window_counter[arr[i - k]] -= 1 # 古い要素を削除
if window_counter[arr[i - k]] == 0:
del window_counter[arr[i - k]] # 0になったら削除
window_counter[arr[i]] += 1 # 新しい要素を追加
print(window_counter) # 各ウィンドウの頻度
辞書順での頻度カウント
頻度が同じ場合、要素を辞書順にソートして出力します。
例題:
頻度順、かつ同頻度の場合は辞書順に並べる。
from collections import Counter
arr = ["apple", "banana", "apple", "cherry", "banana", "apple"]
counter = Counter(arr)
# 頻度順、同頻度なら辞書順
sorted_result = sorted(counter.items(), key=lambda x: (-x[1], x[0]))
print(sorted_result) # 出力: [('apple', 3), ('banana', 2), ('cherry', 1)]
まとめ
これらのパターンを理解しておくことで、競技プログラミングの問題で効率的に活用できます。特に、データの頻度分析や集合演算に役立ちます。