PS:这个系列主要是记录一些让我初见茅塞顿开的算法实现,一些基础的可以取leetocode官网上看题解哈,我这里只会简述一下实现逻辑
题目要求:
求解思路:
1.利用二维矩阵模拟:(n=numRows)
看似是一个N字变换,其实每个周期是一个V字
绿色框选的和红色框选的就是两个周期,然后构建一个矩阵依次输入就行,时间空间复杂度都是O(r*n)
优化思路:压缩矩阵,将空格位置删去,将矩阵每一行初始化为列表,这样能减少空间/时间复杂度O(n)(比较基础就不写代码了)
2.填表法
有点类似压缩矩阵的思想,将每一行都初始化为列表,然后依次向列表中填入,看上图,我们是不是先向下传播,然后再向上传播,当触及顶部或者底部是反弹。
给出代码:(时间空间都是O(n))
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows < 2: return s
res = ["" for _ in range(numRows)]#建立一个n行列表
i, flag = 0, -1
for c in s:
res[i] += c
if i == 0 or i == numRows - 1: flag = -flag
i += flag
return "".join(res)
#"".join()用法:将一个可以迭代的对象,连接成一个字符串
3.直接计算法:
根据位置,直接插入文字,譬如第一行就是从0,2t-2,2*(2t-2),时间复杂度O(n),对每个都遍历了一遍,空间O(n),只用了一个列表存储。
给出代码:
class Solution:
def convert(self, s: str, numRows: int) -> str:
n, r = len(s), numRows
if r == 1 or r >= n:
return s
t = r * 2 - 2
ans = []
for i in range(r): # 枚举矩阵的行
for j in range(0, n - i, t): # 枚举每个周期的起始下标
ans.append(s[j + i]) # 当前周期的第一个字符
if 0 < i < r - 1 and j + t - i < n:
ans.append(s[j + t - i]) # 当前周期的第二个字符
return ''.join(ans)