Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで最大2種類の異なる文字を含む最長部分文字列の長さを求める方法

問題概要

文字列 s が与えられたとき、「異なる文字が最大2種類しか含まれない最長の部分文字列」の長さを求めることを考えます。

例えば、入力が s = "xyzzy" の場合、出力は 4 になります。これは「yzzy」が y と z の2種類の文字のみを含む最長の部分文字列だからです。

解き方:スライディングウィンドウ

この問題は「スライディングウィンドウ(尺取り法)」と呼ばれる手法を使うことで効率的に解けます。各文字の出現回数を記録するマップ(Counter)を用意し、ウィンドウ内の異なる文字の種類数が2を超えないように、左端を調整しながら右端を伸ばしていきます。

具体的な手順は以下の通りです。

  • start := 0(ウィンドウの左端の位置)

  • c := 各文字の出現回数を保持するマップ

  • ans := 0(答えとなる最長の長さ)

  • end を 0 から文字列の長さまで順に動かしながら、以下を繰り返します。

    • c[s[end]] を1増やす(右端の文字をウィンドウに追加)

    • c のサイズ(異なる文字の種類数)が2を超えている間、次の処理を繰り返します。

      • c[s[start]] を1減らす

      • c[s[start]] が0になった場合は、そのキーをマップから削除する

      • start を1進める

    • ansans(end - start + 1) の大きい方の値で更新する

  • 最後に ans を返します。

実装例(Python)

それでは、実際のコードを見てみましょう。

class Solution:
   def solve(self, s):
      from collections import Counter
      start = 0
      c = Counter()
      ans = 0
      for end in range(len(s)):
         c[s[end]] += 1
         while len(c) > 2:
            c[s[start]] -= 1
            if not c[s[start]]:
               del c[s[start]]
            start += 1
         ans = max(ans, end - start + 1)
      return ans
ob = Solution()
s = "xyzzy"
print(ob.solve(s))

入力

s = "xyzzy"

出力

4

計算量について

このアルゴリズムでは、endstart がそれぞれ文字列の長さ分しか移動しないため、時間計算量は O(n) です。また、マップが保持するキーの数は異なる文字の種類数に依存するため、空間計算量も十分に小さく抑えられます。文字列が長くなっても高速に動作するのが、この手法の大きな利点です。

  1. Pythonで二分木の最小共通祖先(LCA)を求めるアルゴリズムと実装例

    はじめに二分木と2つの数値 a、b が与えられたとき、a と b を子孫として持つ最も深いノード(最小共通祖先:LCA)の値を求める問題を考えてみましょう。ここで重要なポイントは、「あるノードはそれ自身の子孫にもなり得る」という点です。つまり、片方のノードがもう片方の祖先である場合、そのノード自体が答えになります。例以下のような二分木を考えます。このとき、a = 6、b = 2 とすると、出力は 4 になります。値4のノードが、6と2の両方を子孫として持つ最も深いノードだからです。解法のアプローチこの問題は再帰を使って効率的に解くことができます。手順は以下の通りです。solve() メソッドを

  2. Pythonで数値が2の累乗かどうかを判定するプログラム

    本記事では、与えられた数値が2の累乗(べき乗)であるかどうかを判定する方法について、考え方と実装手順をわかりやすく解説します。 問題の定義 ある整数 n が与えられたとき、その数が2の累乗(1, 2, 4, 8, 16, …)であるかどうかを判定します。 アプローチ 判定には「繰り返し2で割る」というシンプルな方法を使います。考え方は以下の通りです。 入力された数値 n を、1になるまで繰り返し2で割っていきます(n = n // 2)。 割る過程で n % 2 の結果が0以外(奇数)になり、かつ n が1でない場合は、その数は2の累乗ではありません。 最終的に n がちょうど1になれば、そ