Pythonで共通の文字を持たない2つの単語の最大合計長を求めるプログラム
小文字のアルファベットのみで構成された文字列のリスト words が与えられたとき、互いに共通する文字を1つも持たない2つの異なる単語を選び、その長さの合計の最大値を求める問題を考えてみましょう。
例えば、入力が words = ["abcd", "mno", "abdcmno", "amno"] の場合、出力は 7 になります。これは、共通する文字を持たない単語の組み合わせが ["abcd", "mno"] であり、その長さの合計が 4 + 3 = 7 となるためです。
解決のアプローチ
この問題はビットマスク(bitmask)を使うことで効率的に解くことができます。各単語に出現する文字を26ビットの整数として表現し、2つの単語のビットマスク同士のAND演算結果が 0 になれば、「共通の文字を1つも持たない」と判断できます。
具体的な手順は以下の通りです。
- sign() 関数を定義する — 引数として単語 word を受け取ります。
- value := 0 で初期化します。
- word 内の各文字 c に対して、value := value OR (2^(ord(c) − ord('a'))) を計算します。
- value を返します。
- メイン処理では以下を実行します。
- signature := リスト内の各単語 x に対する sign(x) のリストを作成します。
- ans := 0 で初期化します。
- i を 0 から words のサイズ未満まで繰り返し、さらに j を i + 1 から words のサイズ未満まで繰り返します。
- signature[i] AND signature[j] が 0 と等しい場合、ans := max(ans, len(words[i]) + len(words[j])) を更新します。
- 最後に ans を返します。
それでは、実際の実装を見て理解を深めましょう。
実装例(Pythonコード)
class Solution:
def sign(self, word):
value = 0
for c in word:
value = value | (1 << (ord(c) - 97))
return value
def solve(self, words):
signature = [self.sign(x) for x in words]
ans = 0
for i in range(len(words)):
for j in range(i + 1, len(words)):
if signature[i] & signature[j] == 0:
ans = max(ans, len(words[i]) + len(words[j]))
return ans
ob = Solution()
words = ["abcd", "mno", "abdcmno", "amno"]
print(ob.solve(words))
入力
["abcd", "mno", "abdcmno", "amno"]
出力
7
計算量について
このアルゴリズムの時間計算量は O(n²)(n は単語の数)です。さらに各単語のシグネチャ計算には単語の長さに比例した処理が必要なため、全体としては O(n² + L)(L は全文字数の合計)となります。空間計算量は O(n) です。ビット演算による比較は非常に高速なため、単語数が多い場合でも実用的な速度で動作します。
-
Pythonで同じ長さのリボンをk本切り出せる最大の長さを求めるプログラム
正の整数のリスト(各リボンの長さを表します)と整数 k が与えられます。リボンは何回でも切ることができるので、長さ r のリボンをちょうど k 本作れるような最大の r を求めてください。そのような解が存在しない場合は -1 を返します。たとえば、入力が ribbons = [1, 2, 5, 7, 15]、k = 5 の場合、出力は 5 になります。長さ 15 のリボンを長さ 5 の 3 本に切り分け、長さ 7 のリボンは長さ 2 と 5 に切り分けます。さらに長さ 5 のリボンがもう 1 本あるため、合計で長さ 5 のリボンが 5 本手に入ります。解法のアプローチ:二分探索この問題は二分探
-
Pythonで制約付きの建物の最大高さを求めるプログラム
問題の概要整数 n と制約リスト restrictions が与えられたとします。私たちは都市に n 棟の新しい建物を一列に建てようとしていますが、高さに関するいくつかの制限があります。建物には左から順に 1 から n までの番号が付けられており、各制約は restrictions[i] = (id_i, max_height_i) の形式で表され、「id_i 番の建物の高さは max_height_i 以下でなければならない」ことを意味します。建物の高さに関する都市の規則は以下のとおりです。各建物の高さは 0 以上でなければなりません。1 番の建物(最初の建物)の高さは必ず 0 です。隣接す