LeetCode --- Z字形變換
阿新 • • 發佈:2020-08-08
題目:
將一個給定字串根據給定的行數,以從上往下、從左到右進行 Z 字形排列。
比如輸入字串為 "LEETCODEISHIRING" 行數為 3 時,排列如下:
L C I R
E T O E S I I G
E D H N
之後,你的輸出需要從左往右逐行讀取,產生出一個新的字串,比如:"LCIRETOESIIGEDHN"。
請你實現這個將字串進行指定行數變換的函式:string convert(string s, int numRows);
示例2:
輸入: s = "LEETCODEISHIRING", numRows = 4
輸出:
"LDREOEIIECIHNTSG"
解釋:
L D R
E O E I I
E C I H N
T S G
解題方法
對於n行的Z字形字元序列,可以發現每間隔(2*n-2)個序號為一個週期,假設考慮字串序號從1開始向後排列,那麼
第2n-1個字元和第1個字元都在第一行、
第2n個字元和第2個字元都在第二行、
第2n+1個字元和第3個字元都在第三行、
……
第3n-2個字元和第n個字元都在第n行。
Z字形字元序列的每一行都可以看做一個列表,初始化一個列表res = [[],[],[],...,[]]
,列表有n個元素,每個元素都是一個子列表,子列表內容是按順序出現在對應行的字元。
那麼關鍵需要找到字串每個序號對應Z字形字元序列的行號,定義一個函式為int Z_func(int numRows, int index);
上圖假設n=5,序號16先被模8(2n-2)得到0,但我們期望它序號是8(8 = 0 = 16 mod 8)以方便後面判斷,用8-n取絕對值得到3,表示點16與Z字形最下層的距離distance,然後再用n反向減去distance取絕對值得到5-3=2,就表示了行號2。
再假設序號為15的時候先被模8(2n-2)得到7,用7-n取絕對值得到2,表示點15與Z字形最下層的距離distance,然後再用n反向減去distance取絕對值得到5-2=3,就表示了行號3。
此外還有兩種特殊情況:行數n為1或
程式
class Solution:
def Z_func(self, numRows: int, index: int) -> int:
maxlen = 2*numRows - 2
index %= maxlen
if index == 0:
index += maxlen
distance = abs(numRows - index)
return abs(numRows - distance)
def convert(self, s: str, numRows: int) -> str:
if len(s) == 1 or numRows == 1:
return s
res = []
for i in range(numRows):
res.append([])
for index,value in enumerate(s):
line = self.Z_func(numRows, index + 1)
res[line-1].append(value)
return "".join([j for i in res for j in i])