convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".
所谓的ZigZag,就是以倒N型这样的:
具体来说就是:
关键是要会如何计算各个字符的位置,这就需要数学知识了,根据特殊推导出公式来。
主要是3个公式:
1 之字形行数为nRows,那么每次倒N重复样出现前的间隔字符为ziglen = nRows*2-2,如上图有8行,第一个倒N包含abcdefghijklmn,第二个倒N从接下来的o
开始,我们知道字符o与前面第一个倒N的首个字符位置相差正好ziglen;
2 第一行和最尾一行都是存放一个字符的,所以存储的字符为间隔为ziglen的字符
3 中间行是需要额外存储多一个字符的,存储的字符位置是: ziglen + j - 2*i(其中i为行数,j为该行第几个字符了)
代码:
char* convert(char* s, int numRows) { int l=strlen(s); if(l<3||l<=numRows||numRows<=1)return s; int i,j; char *p=(char *) malloc ((l+10)*sizeof(char)); memset(p,'a',sizeof(p)); int index=0; int ziglen=2*numRows-2; for(i=0;i<numRows;i++){ for(j=i;j<l;j+=ziglen) {p[index++]=s[j]; if(i!=0&&i!=(numRows-1)&&(ziglen+j-2*i)<l) p[index++]=s[ziglen+j-2*i];} } p[index]='\0'; return p; }
下面输出倒N型:
类似上面分析,只不过在输出时注意空格的输出:
1 之字形行数为nRows,那么每次倒N重复样出现前的间隔字符为ziglen = nRows*2-2,如上图有8行,第一个倒N包含abcdefghijklmn,第二个倒N从接下来的o
开始,我们知道字符o与前面第一个倒N的首个字符位置相差正好ziglen;
2 第一行和最尾一行都是存放一个字符的,所以存储的字符为间隔为ziglen的字符,两个非空字符之间相差zigspce=nRows-2个空格;
3 中间行是需要额外存储多一个字符的,存储的字符位置是: ziglen + j - 2*i(其中i为行数,j为该行第几个字符了)。当第一个非空字符靠近左边时,在第1-第zigspace-i列有空格;当靠近右边时有i-1个空格:
void dis(char* s, int numRows) { if(numRows==1)cout<<s; int l=strlen(s); if(l==0||numRows<1)cout<<"NONE"; int ziglen=2*numRows-2; int zigspace=numRows-2; int i,j,k; for(i=0;i<numRows;i++){ for(j=i;j<l;j+=ziglen) {cout<<s[j]; if(i!=0&&i!=numRows-1&&ziglen+j-2*i<l) { for(k=0;k<zigspace-i;k++) cout<<" "; cout<<s[ziglen+j-2*i]; for(k=0;k<i-1;k++) cout<<" "; }//中间行输出:先输出第一个,再是空格,最后还是N型上的字符 else {for(k=0;k<zigspace;k++) cout<<" "; }//第一行和最后一行空格 } cout<<endl; } }