Pythonで無限に繰り返す文字列から部分文字列を抽出する方法
問題概要
文字列 s と2つの整数 i、j(i < j)が与えられているとします。ここで p を、文字列 s を永久に繰り返してできる無限長の文字列と考えます。このとき、p のうちインデックス [i, j) の範囲に該当する部分文字列を求めるのが課題です。
たとえば、入力が s = "programmer"、i = 4、j = 8 の場合、出力は ramm になります。
解法のアプローチ
この問題は、次の手順で解くことができます。
- 結果を格納するための空文字列
pを用意します。 tをiからj - 1まで順にループさせます。- 各ループで、
s[t % len(s)]に相当する文字をpの末尾に連結します。 - ループ終了後、
pを返します。
ポイントは剰余演算(mod)です。無限に繰り返される文字列の n 番目の文字は、元の文字列の (n mod 長さ) 番目の文字と必ず一致します。そのため、実際に巨大な文字列をメモリ上に生成する必要はありません。
実装例
class Solution:
def solve(self, s, i, j):
p = ""
for t in range(i, j):
p += s[t % len(s)]
return p
ob = Solution()
s = "programmer"
i = 4
j = 8
print(ob.solve(s, i, j))
入力
"programmer", 4, 8
出力
ramm
補足:より効率的な書き方
上記の実装は理解しやすい反面、ループ内で文字列を連結するたびに新しい文字列オブジェクトが生成されるため、範囲が大きいと非効率になります。Pythonでは、文字列の繰り返し演算子 * とスライスを組み合わせることで、より簡潔かつ高速に実装できます。
def solve(self, s, i, j):
repeated = s * ((j // len(s)) + 1)
return repeated[i:j]
この方法では、必要な長さ分だけ元の文字列を一括で複製し、あとはスライスで目的の範囲を切り出すだけです。内部処理がCレベルで最適化されているため、i や j が大きい場合でも高速に動作します。用途やデータ規模に応じて、両者の使い分けを検討するとよいでしょう。
-
Pythonで文字のリストを文字列に変換する方法を解説
Pythonでは、リスト内の個々の要素をひとつの文字列にまとめたい場面がよくあります。たとえば、データを保存したり送信したりする際に必要となるシリアライズ(直列化)の処理では、このような変換が非常に役立ちます。具体的には、次のような変換を指します。[h, e, l, l, o, , w, o, r, l, d] → hello worldjoinメソッドを使った変換Pythonには、このような変換を実現するためのjoin()メソッドが標準で用意されています。joinメソッドは、区切り文字(デリミタ)として使う文字列に対して呼び出し、引数に渡したリストの各要素を連結します。今回は各文字をつなげ
-
Pythonでシーケンスのインデックスを使って反復処理する方法
Pythonにおけるシーケンス型オブジェクトとは、リスト・タプル・文字列のように、要素が順序をもって並んでいるデータ構造のことです。それぞれの要素には、0から始まるインデックス(添字)を使ってアクセスできます。この記事では、インデックスを利用してシーケンス内の要素を1つずつ順番に処理する基本的な方法を解説します。range()とlen()を組み合わせた基本形シーケンスの反復処理で最もよく使われるのが、len()関数とrange()関数の組み合わせです。len()でシーケンスの長さを取得し、それをrange()に渡すことで、「0 ~ 長さ-1」までの連続した整数が生成されます。これをfor文で回