leetcode 原题链接:https://leetcode.com/problems/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"
.
简要翻译:对字符串"PAYPALISHIRING"进行给定行数的之字形转换。
例如对于字符串"PAYPALISHIRING"而言,给定行数为3,则其之字形为
P A H N A P L S I I G Y I R然后,逐行读取字符拼接成字符串得到 "PAHNAPLSIIGYIR"
若给定行数为4,则其之字形为
P I N
A L S I G
Y A H R
P I
因此,转换后的字符串为PINALSIGYAHRPI
简要分析:
根据题目意思,我们可以很容易的了解到这道题要我们做的事情。
思路(1)
最直观、最好理解的做法就是生成一个矩阵,存放字符的位置。手动怎么画,我们就怎么生成这个举证
例如,我们有个长度为13的字符串,给定的行数为3,则每个字符在矩阵中的位置如下:
0 4 8 12
1 3 5 7 9 11
2 6 10
其余空的位置为设置为-1;
实现代码:
string convert(string s, int numRows)
{
if (s.size() <= 1 || numRows <= 1)
return s;
vector<vector<int> > matrix;
int index = 0;
vector<int> intVector;
for (int i = 0; i < (s.size()+1) / 2; i++)
{
intVector.clear();
if (i % (numRows-1) == 0)
{
for (int k = 0; k < numRows; k++)
{
intVector.push_back(index++);
}
} else
{
for (int k = 0; k < numRows; k++)
{
intVector.push_back(-1);
}
int pos = numRows - 1 - i % (numRows - 1);
intVector[pos] = index++;
}
matrix.push_back(intVector);
}
string result = "";
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j < (s.size() + 1) / 2; j++)
{
cout << matrix[j][i] << "\t";
if (matrix[j][i] >= 0 && matrix[j][i] < s.size())
{
result += s[matrix[j][i]];
}
}
cout << endl;
}
/*cout << index << endl;
cout << s.size() << endl;
cout << result.size() << endl;*/
return result;
}
这个代码虽然答案是正确的,但是内存超限了。因为在实现的过程中,生成了一个矩阵去保存数据。空间复杂度是O(N* numRows)
这种解法不行,于是就开始思考是否可以从数学规律上去做,于是有了思路2
思路(2)根据下面这个数字矩阵,可以得到启发,即第一行相邻的两个数相差4,第二行相邻的两个数相差2,对应列为2+2(1和5对应0和4)。此处如果规律不明显,可以去绘制一个行数为4的矩阵。我们设定gap为第一行响铃数字差gap = 2*numRows-2,对应列之间数字差为n = gap, m = 0; 每一行的数字差与上一行的关系是n-2, m+2(此处的n, m表示上一行)
0<- gap -> 4 8 12
1<-n-> 3 <-m->5 7 9 11
2 6 10
ps:我这里没有画特别清晰的图,如果有人有需要的话给我评论留言,我有空再过来补吧
具体实现代码:
string convert(string s, int numRows)
{
if (s.size() <= 1 || numRows <= 1)
return s;
string result = "";
int gap = 2 * numRows - 2;
int n = gap, m = 0;
for (int i = 0; i < numRows; i++)
{
int j = i;
while (j < s.size())
{
if (n > 0)
{
result += s[j];
j += n;
}
if (j >= s.size())
break;
if (m > 0)
{
result += s[j];
j += m;
}
}
n -= 2;
m += 2;
}
/*cout << s.size() << endl;
cout << result.size() << endl;*/
return result;
}
这个实现的时间复杂度是o(N),空间复杂度O(1)
ps: 居然是目前(时间2015年8月25日21:23:16)leetcode上cpp提交的最快的代码,着实令我很震惊。