题目描述
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
思路
- 暴力解法,模拟这一变换过程从而得到答案,但是耗时长,内存占用大
- 找规律,我们发现排列的首末行两个字母之间的间距为2n-3,而非首末行的两个字母之间的规律为:若定义首字符为0,则第k个字符为偶数号时,下一个字符的间距为2 * (n- line-1),若k为奇数,则下一个字符的间距为2*line。这种方法仅需要将字符串遍历n次即可
代码
方法一:
string convert(string s, int numRows) {
int len = s.length();
if (len<2 || numRows == 1)
return s;
string res;
int numCols = len / (numRows + numRows - 2)*(numRows - 1);
if (len % (numRows + numRows - 2) != 0)
{
if (len % (numRows + numRows - 2) <= numRows)
numCols++;
else
numCols += 1 + len % (numRows + numRows - 2) - numRows;
}
vector<vector<char>> Matrix(numRows, vector<char>(numCols));
int x = 0, y = 0;
for (int i = 0; i<len; i++)
{
Matrix[x][y] = s[i];
if (y % (numRows - 1) == 0)
{
if (x<numRows-1)
x++;
else
{
x--;
y++;
}
}
else
{
y++;
x--;
}
}
for (int i = 0; i<numRows; i++)
{
for (int j = 0; j<numCols; j++)
{
if (Matrix[i][j] != '\0')
res += Matrix[i][j];
}
}
return res;
}
方法二:
class Solution {
public:
string convert(string s, int numRows) {
int len = s.length();
if (len<2 || numRows == 1)
return s;
string res;
int line = 0;
while (line<numRows)
{
int index = line;
if (line == 0 || line == numRows - 1)
{
while (index<s.length())
{
res += s[index];
index = index + 2 * (numRows-1) ;
}
line++;
}
else
{
int count = 0;
while (index<s.length())
{
res += s[index];
if (count % 2 == 0)
index = index + 2 * (numRows - line-1);
else
index = index + 2 * line;
count++;
}
line++;
}
}
return res;
}
};