The string "PAYPALISHIRING"
is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: “PAHNAPLSIIGYIR”
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3)
should return "PAHNAPLSIIGYIR"
.
题目清晰易懂,就是将字符串分成nRows行呈z字形排列,最后按照一行一行读的方式顺序输出。
题目的主要思路是发现规律,就拿题目举的例子来看:
|0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10|11|12|13
|P |A |Y |P |A |L |I |S |H |I |R |I |N |G
可以看到除了第一个元素p外,凡是下标为2(即3 - 1,nRows - 1)的倍数的元素刚好在拐点上,而其他的元素就在中间,向下或者向上排列,而且具体向上还是向下也好判断:经过上方的拐点后,开始向下排列,经过下方的拐点后开始向上排列。
这么来看的话,这题的解题思路就很清晰了,初始时排列方向必然向下(题目默认开始向下排列Z字),遇到元素下标为2的倍数时就到了拐点,此时排列方向转换,其他情况时用一个变量row标记当前应该输出之第几行,输出至对应的行内即可。
class Solution(object):
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
orient = 1 #1向下,-1向上
row = 0
ans = [[] for row in range(numRows)] #2维列表初始化
for index, i in enumerate(s):
if index == 0:
ans[0].append(i)
row = 1 #下个必然第二行
elif index % (numRows - 1) == 0: #到达转折点
if orient == 1: #从下向上转折
ans[numRows - 1].append(i)
orient = -1
row = numRows - 2 #必然倒数第二行
else: #从上向下转折
ans[0].append(i)
orient = 1
row = 1 #必然第一行
else :
ans[row].append(i)
row = row + orient #这里比较trick,本来orient是用0,1标记方向的,但是突然发现改成1,-1后可以方便的进行row的计算,否则还得判断orient的方向,对row进行加或减的操作
res = ""
for i in ans:
for j in i:
res = res + j #这个方法会快些
return res
最后输出ans也可以这么写,可以偷懒,但是时间消耗会多些,估计是join函数的问题
for i in ans:
res = res + "".join(i)
总结
总的来说,这题我单纯觉得好玩,学习到的地方有多维列表初始化的方法,还有将列表转成string类型输出时,join方法并不够快,2333