Pythonで1つ目の文字列の文字から2つ目の文字列を作成できるか判定する方法
問題の概要
2つの文字列 s と t が与えられたとき、t を s に含まれる文字だけを使って作れるかどうかを判定する問題です。ここで重要なのは、s の各文字は一度しか使えないという点です。
例えば、入力が s = "owleh"、t = "hello" の場合、s の文字を組み合わせることで t が作れるため、出力は True になります。
解決のアプローチ
この問題は「文字の出現回数(頻度)を数える」というシンプルな発想で解けます。手順は以下の通りです。
sの各文字とその出現回数を記録したマップ(freq)を作成するtの先頭から順に各文字を確認するfreq[t[i]]が 0 の場合、必要な文字がもう残っていないのでFalseを返す- そうでなければ
freq[t[i]]を 1 減らして次の文字へ進む
- すべての文字を消費できたら
Trueを返す
実装例(Pythonコード)
from collections import defaultdict
def solve(s, t):
freq = defaultdict(int)
# s の各文字の出現回数をカウント
for i in range(len(s)):
freq[s[i]] += 1
# t の各文字が s に十分あるか確認
for i in range(len(t)):
if freq[t[i]] == 0:
return False
freq[t[i]] -= 1
return True
s = "owhtlleh"
t = "hello"
print(solve(s, t))入力
s = "owhtlleh" t = "hello"
出力
True
よりPythonicな書き方:Counterを使う方法
標準ライブラリの collections.Counter を使うと、同じ処理をもっと簡潔に書くことができます。
from collections import Counter
def solve(s, t):
return not (Counter(t) - Counter(s))
s = "owhtlleh"
t = "hello"
print(solve(s, t)) # TrueCounter(t) - Counter(s) は、「t に必要だが s には足りない文字」だけを残します。結果が空であれば、s の文字だけで t を作れることになります。
計算量
- 時間計算量: O(n + m)(n は
sの長さ、m はtの長さ) - 空間計算量: O(k)(k は出現する異なる文字の種類数)
まとめ
文字の頻度を管理することで、アナグラムのような判定問題を効率よく解くことができます。defaultdict や Counter を活用すれば、コードも短く読みやすくなります。ぜひ実際にコードを動かして挙動を確かめてみてください。
-
Pythonで左右の部分木の入れ替えにより2つの二分木を一致させられるか判定する方法
問題の概要 2つの二分木が与えられたとき、任意のノードについて左部分木と右部分木を何度でも入れ替えてよいと仮定します。この操作を繰り返すことで、1つ目の木を2つ目の木とまったく同じ形に変換できるかどうかを判定するのが、この記事で扱う問題です。 例えば、次のような2つの木が入力として与えられた場合、左右の入れ替えによって一致させられるため、出力は True になります。 解決のアプローチ この問題は、幅優先探索(BFS)の考え方を使い、木をレベル(深さ)ごとに処理しながらノードの値を比較することで解けます。左右の入れ替えによって同じレベル内の値の並び順は反転し得るため、「順方向」または「逆方
-
Pythonで文字列が指定したサフィックス(接尾辞)リストのいずれかで終わるかどうかを確認する方法
endswith()メソッドを使う方法 Pythonの文字列クラスには、endswith()メソッドが用意されています。このメソッドは、検索したい文字列のタプルを受け取り、文字列オブジェクトに対して呼び出します。以下のように使用できます。 string = core java print(string.endswith((txt, xml, java, orld))) 実行結果 True タプル内のいずれかのサフィックスで文字列が終わっていればTrueが返され、どれにも該当しなければFalseが返されます。シンプルな判定であれば、この方法が最も可読性が高くおすすめです。 正規表現(re.sea