将一个给定字符串 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);
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3 输出:"PAHNAPLSIIGYIR"
示例 2:
输入:s = "PAYPALISHIRING", numRows = 4 输出:"PINALSIGYAHRPI" 解释: P I N A L S I G Y A H R P I
示例 3:
输入:s = "A", numRows = 1 输出:"A"
提示:
1 <= s.length <= 1000
s
由英文字母(小写和大写)、','
和 '.'
组成1 <= numRows <= 1000
思路:找规律,为了方便理解,可以自己在草稿本上把numRows=5和6的情况画出来;
第一行相邻两两数之间的下标差是2*numRows-2;
以输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
为例。P的下标为0加上2*4-2之后也就是6,下标为6的位置就是I;
最后一行规律和第一行一样。
现在就是中间有所不同,一个完整的N里面第一行和最后一行都只有两个字符,其它位置则有三个字符,可以将同一行相邻之间的距离加起来,然后找规律。
还是以上面的为例,第二行中,A和L和S之间总的间隔为6,第三行中,Y和A和H之间的间隔也为6.这是 numRows=4的情况,将等于3,5,6的情况列出来找规律就能发现,和为2*numRows-2,
第一个数和第二个数之间的距离为2 * numRows - 2 - 2 * j。j是N字形中的所在行的下标。第二个数和第三个数之间的距离是2*j;
char* convert(char* s, int numRows) {
char* a = (char*)malloc(sizeof(char) * (strlen(s)+1));
int i = 0;
if ((2 * numRows - 2)==0)//如果numRows等于1直接返回
{
return s;
}
for (int j = 0; j < strlen(s); j += 2 * numRows - 2)//处理第一行
{
a[i++] = s[j];
}
for (int j = 1; j < numRows - 1; j++)//处理中间
{
for (int k = j; k < strlen(s);)
{
a[i++] = s[k];
k += 2 * numRows - 2 - 2 * j;
if (k >= strlen(s))//可能不是完整的N字,完整的N中间的行有3个数,要操作两次,判断操作完一次之后是否越界了。
{
break;
}
a[i++] = s[k];
k += 2 * j;
}
}
for (int j = numRows - 1; j < strlen(s); j += 2 * numRows - 2)//处理最后一行
{
a[i++] = s[j];
}
a[i] = '\0';
return a;
}