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为6,例子中不以字符表示,而是以数组下标的形式给出:
0 10
1 9 11
2 8 12
3 7 13 17
4 6 14 16
5 15
除了第一行和最后一行,在一个循环0–9之间,中间的序列都出现了两次。我们可以得到一个循环的个数onelen = 2*nRows – 2;那么第0行两个之间的间距为onelen,第一行间距为onelen – 1 – 1;….第i行间距为onelen – 2*i;我们也尝试将第0行和最后一行统一到一个循环中,但是有些复杂,所以就另外做了判断,单独处理;同时在输出一行时,将中间的每一行再分成onelen为个数的循环,每次输出两个。
这样实现起来很容易,但是我们必须要考虑多种可能情况,包括无效的输入等等。
有了以上的公式,我们就可以写出代码了。但需要注意几点:
1.判断所求出的下标是不是越界了,即不能超出原字串的长度;
2.注意处理nRows=1的情况,因为它会使差值2 * nRows – 2的值为0,这样下标值会一直不变,进入死循环,产生
Memory Limit Exceeded 或者 Output Limit Exceeded之类的错误。
3.还有一些其他的边界情况,如:nRows > s.length,s.length = 0等需要处理。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ConvertStr(char *str,int nRows)
{
int onelen = 2*nRows - 2;
int index;
int n = strlen(str);
if(nRows<0 || nRows > n){ //处理一些非法输入!
printf("the rows doesn't correct!");
return;
}
if(nRows == 1){ //当nRows为1的时候,onelen就为0,不再增加,会陷入死循环!
printf("%s",str);
return;
}
for(int i = 0;i < nRows;++i){
index = i;
if(i == 0 || i == nRows-1){
while(index < n){
printf("%c",str[index]);
index = index+onelen;
}
}else{
while(index < n){
printf("%c",str[index]);
int temp = index + onelen - 2*i;
if(temp > n)
break;
printf("%c",str[temp]);
index = index + onelen;
}
}
}
}
int main(void)
{
char *str = "PAYPALISHIRING";
ConvertStr(str,-1);
return 0;
}
思路二:
还有另外一种考虑,我们设char arr[nRows][strlen(str)]数组。我们将str指向的字符串按照列从上到下再从下到上,依次循环给每一行分配一个元素。这个也好实现,不过有些复杂,需要为每一行都在设置个lenth,表示存储了多少元素,以便下一个元素能很快存储。最后再给每一行末尾添加空字符,最后再输出即可。
但是利用C++的话,就很好实现了,给容器添加元素,直接加即可。没有过多的考虑。
代码如下:
class Solution {
public:
string convert(string s, int nRows)
{
string ret;
int n=s.size();
vector<string>v(nRows);
for(int i=0;i<n;)
{
for(int j=0;j<nRows&&i<n;j++,i++)
v[j]+=s[i];
for(int j=nRows-2;j>0&&i<n;j--,i++)
v[j]+=s[i];
}
for(int i=0;i<nRows;i++)
{
for(int j=0;j<v[i].size();j++)
ret+=v[i][j];
}
return ret;
}
};