将一个给定字符串 s
根据给定的行数 numRows
,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING"
行数为 3
时,排列如下:
P A H N A P L S I I G Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
char* convert(char* s, int numRows)
{
//用二维数组去存放整个字符串
//把整个数组扫描,按顺序打印不为空的位置的元素
int n = strlen(s), r = numRows;
//如果行数为1,或者行数大于字符个数
//按照要求排完之后任然是原数组
if (r == 1 || r >= n)
{
return s;
}
//假设numRows 行数是r
//那么就要竖着存放r个字符
//把第r+1个字符放到第r个字符的右上方
//直到回到第一行
//我们这里把回到第一行看作一个周期
//就是从第一行的第一个字符开始
//到第一行第二个字符是一个周期
//那么一个周期要有r+r-2个字符
//所以周期t=2*r-2
//我们把最后一个周期,字符不够的情况也看作一个周期
//不够的字符用0填补
int t = r * 2 - 2;
//整个二维数组的列数
//周期数*每个周期的列数
//周期数就是字符个数除以周期取整加1
//n/t+1
//或者(n+t-1)/t
//把不够的补上
int c = (n + t -1) / t * (r - 1);
//开辟一个二维数组
char ** mat = (char **)malloc(sizeof(char *) * r);
for (int i = 0; i < r; i++)
{
mat[i] = (char *)malloc(sizeof(char) * c);
//把二维数组全部置为0
memset(mat[i], 0, sizeof(char) * c);
}
for (int i = 0, x = 0, y = 0; i < n; ++i)
{
mat[x][y] = s[i];
//如果没有超过行数
//也就是竖着还没有放满
if (i % t < r - 1)
{
++x; // 向下移动
}
else
{
--x;
++y; // 向右上移动
}
}
int pos = 0;
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
if(mat[i][j])
{
s[pos++] = mat[i][j];
}
}
free(mat[i]);
}
free(mat);
return s;
}