问题描述

题目要求实现Z字形变换,即将给定的字符串按照Z字形排列后,再按行输出。例如,给定字符串 "LEETCODEISHIRING" 和行数 numRows = 3,我们可以得到以下排列:

L   C   I   R
E T O E S I I G
E   D   H   N

然后按行输出结果:LCIRETOESIIGEDHN。

解决思路

我们可以根据题目要求找到一种规律来解决这个问题。观察Z字形排列,可以发现第一行和最后一行中的字符之间的位置关系存在一个公式,即第 i 行和第 i+1 行中的相邻字符之间距离是 numRows * 2 - 2。同时,除了第一行和最后一行,其他行还存在两个字符之间距离的关系,即第 i 行和第 i+1 行中的相邻字符之间距离是 numRows * 2 - 2 * (i + 1)。

代码实现

func convert(s string, numRows int) string {
    if numRows == 1 {
        return s
    }
    
    var res bytes.Buffer
    n := len(s)
    cycleLen := numRows*2 - 2
    
    for i := 0; i < numRows; i++ {
        for j := 0; j+i < n; j += cycleLen {
            res.WriteByte(s[j+i])
            if i != 0 && i != numRows-1 && j+cycleLen-i < n {
                res.WriteByte(s[j+cycleLen-i])
            }
        }
    }
    
    return res.String()
}

上述代码中,我们通过双重循环遍历字符串,外层循环控制行数,内层循环控制每一行中的字符位置。根据前面所述的规律,采用了递增和递减的方式来确定每一个字符的位置,并使用字符串拼接的方式得到最终的结果。

复杂度分析

时间复杂度:O(n),其中 n 是字符串 s 的长度。每个字符被访问一次。

空间复杂度:O(n)。除去存储结果的字符串外,我们只需要常数空间来存储循环长度和循环次数的变量。