ZigZag Conversion
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 RAnd 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"
.
题意分析:
因为我本人是做视频编解码的,所以一听到zigzag扫描自然而然的想到了DCT变换里面的之字形扫描(如下图),但是这么验证一下题意发现不对。
题目意思的扫描书序其实是下图酱紫的。
思路一
如下图所示,字符串s是一行分配一个字符,然后再反过来。我的想法是建一个vector<string> strlist(nRows),扫描字符串,然后给每一个vector里面的string拼接上一个字符。
这样nRows的字符串都得到了,再将所有strlist里的字符串都拼接起来就得到我们的结果。算法复杂度为O(n),但是空间复杂度是需要建一个包含nRows个string的vector。
代码如下:
class Solution
{
public:
string convert(string s, int nRows)
{
int i=0, j=0;
string result = "";
vector<string> strlist(nRows);
vector<string>::iterator iter;
bool flag = false;
for(i=0;i<s.length();i++)
{
strlist[j] += s[i];
if(0 != nRows-1)
{
if(!flag)
j++;
else
j--;
if(j%(nRows-1) == 0)
flag = !flag;
}
}
for(iter=strlist.begin();iter<strlist.end();iter++)
{
result += *iter;
}
return result;
}
};
思路二
为了避免如上面思路那样开辟nRows个string,我们可以尝试找一下数字规律。
规律如下:
1、第一行和最后一行数据间隔是2*(nRows-1);
2、4 = 2+2*(nRows-1)-2*2;10=8+2*(nRows-1)-2*2;5=1+2*(nRows-1)-2*1;11=7+2*(nRows-1)-2*1;
从这里可以看出是有一定规律的,下图已经很清楚的将这个规律给展示出来了。
这个算法复杂度也是O(n)
上代码吧,看不懂图的请留言吧,我表示语言能力太弱,解释不了。
参考链接:http://www.myexception.cn/other/1676954.html
class Solution
{
public:
string convert(string s, int nRows)
{
if (nRows <= 1)
return s;
string result = "";
int i=0, j=0; //i表示行,j表示s下标,k表示result下标
int step = 2*(nRows-1);
for(i=0; i<nRows; i++)
{
for(j=i; j<s.length();j+=step)
{
result += s[j];
if(i==0 || i == nRows-1)
continue;
//如果不是第一行或者最后一行,则还有一个斜线上的数据
int slash = j + step -2*i;
if(slash < s.length())
result += s[slash];
}
}
return result;
}
};
最后附上Zig-zag打印的程序片段(程序来源: http://www.2cto.com/kf/201311/259392.html)
void printZigzag(const string &s, int nRows)
{
if(s.empty() || nRows < 1) return;
if (nRows == 1)
{
cout<<s<<endl;
return;
}
int zigSpan = nRows*2 - 2;
int zig = nRows - 2;
for (int i = 0; i < nRows; i++)
{
for (int j = i; j < s.length(); j+=zigSpan)
{
cout<<s[j];
//注意:推导出zigSpan+j-2i的数学公式,一点都不能错
if (i != 0 && i != nRows-1 && zigSpan+j-2*i<s.length())
{
for (int r1 = 0; r1 < zig-i; r1++)
{
cout<<" ";
}
cout<<s[zigSpan+j-2*i];
for (int r2= 0; r2 < i-1; r2++)
{
cout<<" ";
}
}
else
{
for (int r = 0; r < zig; r++)
{
cout<<" ";
}
}
}
cout<<endl;
}
}
打印结果展示