题目:
将字符串 "PAYPALISHIRING"
以Z字形排列成给定的行数:
P A H N
A P L S I I G
Y I R
之后从左到右"PAHNAPLSIIGYIR"
实现一个将字符串进行指定行数变换的函数。
思路:
1. 官方答案版本1
以上面这个例子解释:
遍历原始字符串,用currow变量记录所处的行,即让currow变换为0,1,2,1,0,1,2,1,0,1,2,1,0,1......
(如果numRows是4行currow就是0,1,2,3,2,1,0,1,2,3,2,1...... )
同时初始化一个长度为3,元素为字符串的列表rows。
每到currow行,就把遍历到的字符s加入到rows相应元素,
如第0行,rows[0]+=s,第1行,rows[1]+=s ...... 最后再把rows按顺序输出就好了。
如何让currow按需变换,需要再有个变量godown 记录方向,到0或numRows-1 行的时候,godown变向,决定currow加一或者减一。
需要注意
①原字符串长度可能小于numRows,所以列表长度为min(numRows, len(s))
②遇到numRows = 1,直接return s。
class Solution:
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
rows = ['']* min(numRows, len(s))
godown = False
currow = 0
for c in s:
rows[currow] += c
if currow == 0 or currow == numRows-1:
godown = not godown
if godown:
currow += 1
else:
currow -= 1
return ''.join(rows)
2. 官方答案版本2
主要是找出数字索引与行列数的关系。
0 | 4 | 8 | 12 | |||
1 | 3 | 5 | 7 | 9 | 11 | 13 |
2 | 6 | 10 |
numRows有3行,完全有数字的列,间隔interval=4,(4=2*3-2)
第0行:0,4,8,12...... (从0开始间隔4)
第numRows-1行:2,6,10...... (从numRows-1开始间隔4)
第1行:1,5,9,13... 也是间隔4,然后3比1大2, 7比5大2,11比9大2... (行内间隔innergap=2)
0 | 6 | 12 | ||||
1 | 5 | 7 | 11 | 13 | ||
2 | 4 | 8 | 10 | |||
3 | 9 |
numRows=4,interval=2*4-2=6。第0行和最后一行规律同上。
主要看innergap的规律,5---1,2---4的和都是6(interval),我们想求的是5减1,4减2,即innergap = interval - 2*i(i是行序号)
这个方法好像比上一个慢,不知道是不是对字符串s的访问太跳跃的原因>.<
class Solution:
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
ans = ''
interval = 2*numRows -2
ans += s[::interval] #第0行,第一个例子里的0,4,8
for i in range(1, numRows-1): #第1到倒数第2行
innergap = interval - 2*i
for j in range(i, len(s),interval):
ans += s[j] #例子里的1,5,9
if j + innergap < len(s): #注意越界
ans += s[j+innergap] #例子里的3,7
ans += s[numRows-1::interval] #最后1行,例子里的2,6
return ans
发现, i、j循环里,j+innergap每次都要判断越界,稍微改进直到一行最后才判断,会变快^0^
for i in range(1, numRows-1): #第1---倒数第2行
innergap = interval - 2*i
j = i
while j