Pythonで解く細胞融合問題 ― heapqを使った効率的なアルゴリズム実装
問題の概要
数値のリスト cells があるとします。このリストは、さまざまな細胞のサイズを表しています。
各反復処理において、最も大きい2つの細胞 a と b が次のルールに従って相互作用します。
- a = b の場合: 両方の細胞は死滅します。
- a ≠ b の場合: 2つの細胞は融合し、新しいサイズは
floor((a + b) / 3)(小数点以下切り捨て)になります。
最終的に残った細胞のサイズを求めてください。すべての細胞が消滅した場合は -1 を返します。
具体例
入力が [20, 40, 40, 30] の場合、出力は 16 になります。
- 1回目の反復:最大の2つである
40と40は等しいため、両方とも死滅します。 - 2回目の反復:残った
20と30が融合し、floor((20 + 30) / 3) = floor(50 / 3) = 16となります。
結果として、最後の細胞のサイズは 16 です。
解決のためのアプローチ
この問題を解くには、以下の手順に従います。
cellsの各値を負の値に変換します。- 変換したリストでヒープを構築します。
- ヒープに要素が2つ以上残っている間、以下を繰り返します。
- ヒープから2つの要素を取り出し、符号を元に戻してそれぞれ
first(最大値)、second(2番目に大きい値)とします。
- ヒープから2つの要素を取り出し、符号を元に戻してそれぞれ
firstとsecondが等しくない場合は、floor((first + second) / 3)を再び負にしてヒープへ挿入します。- 処理終了後、ヒープに要素が残っていれば
-cells[0]を返し、空であれば-1を返します。
ポイント: Python標準ライブラリの heapq は最小ヒープのみをサポートしています。そこで、値をあらかじめ負に変換しておくことで、最大の要素を先頭に取り出せる「最大ヒープ」として利用できます。
実装例
from heapq import heapify, heappop, heappush
class Solution:
def solve(self, cells):
# 各値を負に変換することで最大ヒープとして扱う
cells = [-x for x in cells]
heapify(cells)
while len(cells) > 1:
# 最大の2つの細胞を取り出す
first, second = -heappop(cells), -heappop(cells)
if first != second:
# 融合後のサイズを計算してヒープに戻す
heappush(cells, -((first + second) // 3))
return -cells[0] if cells else -1
ob = Solution()
cells = [20, 40, 40, 30]
print(ob.solve(cells))入力
[20, 40, 40, 30]
出力
16
計算量について
このアルゴリズムでは、各反復ごとにヒープへの挿入・削除を行います。ヒープ操作の計算量は O(log n) であるため、全体の時間計算量は O(n log n)、空間計算量は O(n) となります。これにより、大量のデータに対しても効率的に処理できます。
-
【初心者向け】Pythonのissuperset()メソッドの使い方をわかりやすく解説
はじめにこの記事では、Pythonのissuperset()メソッドについて、基本的な仕組みから実際のコード例まで詳しく解説します。issuperset()は、セット(集合)に対して使用できるメソッドで、引数として渡されたセットのすべての要素が、呼び出し元のセットに含まれているかどうかを判定します。呼び出し元のセットBが、引数のセットAのすべての要素を含んでいる場合 → True を返すセットAの要素がすべてBに含まれていない場合 → False を返すつまり、「BがAの上位集合(スーパーセット)であるかどうか」を判定するためのメソッドです。基本構文B.issuperset(A)この式は、Bが
-
Microsoft Excelでセルを分割する3つの方法|初心者向け完全ガイド
Excelでは、1つのセルに複数のデータが入ってしまうことがあります。これは、複数のスプレッドシートを統合したり、外部からデータをインポートしたりする際によく発生します。そのまま我慢して使うこともできますが、Microsoft Excelにはセルを分割する機能が備わっています。ただし、単純な「分割」ボタンがあるわけではなく、目的に応じていくつかの異なる方法を使い分ける必要があります。方法1:「区切り位置」機能を使うMicrosoftが公式に推奨しているのは、「区切り位置」ウィザードを使う方法です。この方法では、分割対象のセルのすぐ右隣にあるセルの内容が上書きされるため、データを失わないよう、あ