The string "PAYPALISHIRING"
is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N A P L S I I G Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3)
should return "PAHNAPLSIIGYIR"
.
首先,我们来看这个字符串有什么规律。以nRows=3为例来分析。
对于第一行的字符,P,A,H,N在原字符串中的位置分布为0,4,8,12.他们之间的间隔都是4,为2*(nRows-2)+2=2*nRows-2,为什么会是这个公式呢?看下图
怎么样,很清晰吧,除了第一行和最后一行,中间方框内是两倍的nRows-2,当然再加上两个圆圈的两个1,就有了上面那个公式了。
同样的,最后一行也是这样的。所以,第一行和最后一行的字符可以直接通过公式找到对应的index得到了吧。
下面,我们来继续看中间的除了第一行和最后一行之外的行数他们的情况是怎样的。
我们以nRows=4那张图为例来看,上面我们算出I和P之间的距离是2*nRows-2,A其实是在P的后面的i个,其中i是行数,且第一行是0(这也符合数组的写法).L在I的前面的i个。所以A和L之间的距离就应该是2*nRows-2-2*i。
而L和S之间的距离,因为L距I的距离是i。I和S之间的距离也是i,所以这两者之间的距离就是2*i。后面S和I之间的具有又是2*nRows-2-2i了。
所以,我们可以发现除了第一行和最后一行,中间的所有行,之间的间隔并不是固定,而是a,b,a,b这样交叉的,其中a=2*nRows-2-2*i; b=2*i;,
有了这样的分析,再看代码就简单多了。
char* convert(char* s, int numRows) {
if(s == NULL || numRows <= 0)
{
return NULL;
}
if(numRows == 1)
{
return s;
}
int interval = 0;
int s_len = strlen(s);
char* result = malloc(s_len + 1);//need to malloc one more, just for \0
int index = 0;
if(result == NULL)
{
//TODO, memory allocate error...
return NULL;
}
interval = 2 * numRows - 2;
//first row
for(int i = 0; i < s_len; i += interval)
{
result[index++] = s[i];
}
//second row to last -1 row
for(int j = 1; j < numRows -1; j++)
{
int gap = (j << 1);
for(int i = j; i < s_len; i += gap)
{
result[index++] = s[i];
gap = interval - gap; //first interval is interval - 2i, than 2i, than interval - 2i...
}
}
//last row
for(int i = numRows - 1; i < s_len; i += interval)
{
result[index++] = s[i];
}
result[index] = '\0';
return result;
}
更多精彩内容请访问:www.dlvoice.com