Z字形变换
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:
解法1:
将倒着的z字形变成立着的z字形,例如:s = “LEETCODEISHIRING”
用一个二维数组按行存储它,没有字符的位置不做修改。最后读取的时候按列读取。
实现代码:
class Solution {
public:
string convert(string s, int numRows) {
if (s.size() <= numRows ||numRows<=1) return s;//排除不需要排列的情况
int len = s.size();
vector<vector<char> > pos(len, vector<char>(numRows));//创建二维动态数组
int k = 0;//记录已存的字符个数
int flag = numRows-1;//标志中间字符应存位置
for (int i = 0; i < len; i++)
{
for (int j = 0; j < numRows; j++)
{
if (i % (numRows - 1) == 0 || numRows == 2)//Z字的上下横情况,numRows =2时没有斜线情况
{
pos[i][j] = s[k];
k++;
}
else if (j == flag - 1)//Z字的斜线情况
{
pos[i][j] = s[k];
k++;
flag--;
}
else//无字符情况
continue;
if (k == len)//存储完成
break;
}
if (k == len) break;
if(flag==1)//斜线存储完成,还原标志
flag = numRows-1;
}
string res;//存储结果
for (int j = 0; j <= numRows; j++)
{
int count = 0;//记录连续遍历到无字符数组的次数
for (int i = 0; i < len; i++)
{
if (j % (numRows - 1) == 0 && pos[i][j] != '\0')//首尾列字符情况
{
res = res + pos[i][j];
i = i + numRows - 2;
count = 0;
continue;
}
else if (j % (numRows - 1) != 0 && pos[i][j] != '\0')//中间列字符情况
{
res = res + pos[i][j];
count = 0;
continue;
}
else//无字符情况
count++;
if (count >= numRows)//连续numRows次遍历到无字符数组位置,则break;
break;
}
if (res.size() == len) break;
}
return res;
}
};
该方法容易理解但是时间空间效率不高;
解法2:
行方向:从第一行向最后一行扫描,到最后一行向第一行扫描。
列方向:从左向右扫描。
用大小为numRows的数组存储每一行构成的字符串,最后连接每一行的字符串
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1||s.size()<=numRows) return s;
vector<string> rows(numRows);
int curRow = 0;//当前扫描行
bool goingDown = false;//true为向下扫描,false为向上扫描
for (char c : s) {
rows[curRow] += c;
if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;//到首行和尾行改变方向
curRow += goingDown ? 1 : -1;
}
string ret;//存放结果
for (string row : rows) ret += row;
return ret;
}
};