Pythonで文字列をk行のジグザグパターンに変換するプログラムを解説
文字列 s と整数 k が与えられたとき、s の各文字を順に取り出し、左上から右下へ斜めに進んで k 行目に達したら、今度は右上へ折り返す――この動きを繰り返してできる「ジグザグ型」の文字列を作成する方法を解説します。
たとえば、入力が s = "ilovepythonprogramming"、k = 5 の場合、出力は次のようになります。

解法のアプローチ
この問題は、いわゆる「蛇行(ジグザグ)パターン」への文字列変換です。各行にどの文字がどの位置に来るかを記録しておき、最後に行単位で組み立てるのがポイントです。具体的には、次の手順で解きます。
- 初期化:各行の文字情報を格納する辞書
lineを用意し、現在の行番号cntを 0、移動方向deltaを 1(下向き)に設定します。 - 文字の割り当て:文字列
sの各インデックスiと文字cについて、ペア(c, i)をline[cnt]の末尾に追加します。 - 方向の反転:
cntにdeltaを加算しながら進み、cntがkに達したら方向を反転(delta = -1)してcntをk - 2に戻します。逆にcntが 0 になったら、再び下向き(delta = 1)に切り替えます。 - 結果の組み立て:辞書
lineの各行について、元の文字列と同じ長さの空白文字リストprefixを作成し、記録しておいた位置yに文字xを埋め込みます。その後、リストの要素を連結して 1 行分の文字列にし、ansに追加します。 - 出力:
ansの各行を改行文字で連結した文字列を返します。
理解を深めるために、以下の実装例を見てみましょう。
実装例
from collections import defaultdict
class Solution:
def solve(self, s, k):
line = defaultdict(list)
cnt = 0
delta = 1
for i, c in enumerate(s):
line[cnt].append((c, i))
cnt += delta
if cnt == k:
delta = -1
cnt = k - 2
if cnt == 0:
delta = 1
ans = []
for i, c in line.items():
prefix = [" "] * (len(s))
for x, y in c:
prefix[y] = x
ans.append("".join(prefix))
return "\n".join(ans)
ob = Solution()
s = "ilovepythonprogramming"
k = 5
print(ob.solve(s, k))
入力
"ilovepythonprogramming", 5
出力

計算量の目安
文字列の長さを n とすると、各文字を一度ずつ処理するため時間計算量は O(n) です。一方、行ごとの結果を保持するために O(n × k) のメモリを使用します。k が極端に大きくない限り、十分に高速に動作するシンプルで効率的なアルゴリズムです。
-
【初心者向け】Pythonのcasefold()メソッドで大文字小文字を無視した文字列比較を行う方法
このチュートリアルでは、Pythonの文字列メソッドstr.casefold()について詳しく解説します。このメソッドは引数を一切受け取らず、戻り値として「大文字小文字を区別しない比較(ケースレス比較)」に適した文字列を返します。 casefold()とは何か? そもそも「ケースレス比較(caseless comparison)」とは何でしょうか。例えば、ドイツ語の小文字ß(エスツェット)は、ssと等価な文字として扱われます。str.casefold()メソッドを使うと、ßがssに変換されます。つまり、casefold()はすべての文字を小文字に変換するだけでなく、こうした特殊な文字の等価変換
-
Pythonで16進数の文字列を10進数に変換する方法を解説
この記事では、16進数の文字列を10進数に変換する問題の解決策について詳しく解説します。課題の概要16進数形式の文字列が与えられたとき、それを対応する10進数の値に変換することを目標とします。例えば、16進数の「F」は10進数では「15」に相当します。この問題には主に2つのアプローチがあります。力ずく(ブルートフォース)な手法:int関数を使った明示的な型変換組み込みモジュールを活用する手法:astモジュールのliteral_eval関数を使用方法1:int関数を使った変換最もシンプルで一般的な方法は、Pythonの組み込み関数であるint()を利用するものです。この関数は2つの引数を受け取り