[C++]ZigZag Conversion 之字形转换

来源:互联网 发布:雅思测试软件 编辑:程序博客网 时间:2024/05/22 05:23

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   NA P L S I I GY   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".

简要翻译:对字符串"PAYPALISHIRING"进行给定行数的之字形转换。

例如对于字符串"PAYPALISHIRING"而言,给定行数为3,则其之字形为

P   A   H   NA P L S I I GY   I   R
然后,逐行读取字符拼接成字符串得到"PAHNAPLSIIGYIR"

若给定行数为4,则其之字形为

P IN

A LS I G

Y AH R

P I

因此,转换后的字符串为PINALSIGYAHRPI


简要分析:

根据题目意思,我们可以很容易的了解到这道题要我们做的事情。

思路(1)

最直观、最好理解的做法就是生成一个矩阵,存放字符的位置。手动怎么画,我们就怎么生成这个举证

例如,我们有个长度为13的字符串,给定的行数为3,则每个字符在矩阵中的位置如下:

0 48 12

1 35 7 9 11

2 610

其余空的位置为设置为-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 610

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提交的最快的代码,着实令我很震惊。


0 0