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"
.
class Solution { public: string convert(string s, int nRows) { int len = s.length(); if (len < 2 || nRows == 1 || len < nRows) return s; vector<string> cols; int si = 0; int ri = 0; while (si < len) { bool inacol = cols.size() % (nRows-1) == 0; if (!inacol) { for (int i=0; i<nRows - 2 && si <len; i++, si++) { cols.push_back(s.substr(si, 1)); // a char as a single column } continue; } cols.push_back(string()); for (int i=0; i<nRows && si<len; i++, si++) { cols.back().push_back(s[si]); // all char in a column } } string res; int nCols = cols.size(); int stepa = nRows - 1; int stepb = 0; for (int i=0; i<nRows; i++) { bool usea = false; int last = -1; for (int j = 0; j < nCols; j += usea ? stepa : stepb) { usea = !usea; if (j == last) continue; last = j; int r = i, c = j; if (cols[c].length() < 1) break; if (c % (nRows - 1) != 0) { r = 0; } else if (cols[c].length() - 1 < r) { break; } res.push_back(cols[c][r]); } --stepa, ++stepb; } cols.clear(); return res; } };
一般来说那么长,时间又是100ms+的代码定不是好的!
发现一个以前没注意到的问题,如下代码:
string a("abc"); string b; b.push_back(a[10]); cout<<b.length()<<endl;
编译运行并不会报错,虽然其中a[10]的操作明显越界了,但是与数组不同,字符串的下标操作当越界时会返回一个NULL字符,去http://www.cplusplus.com/查了一下,上面是这么说的:
If pos is equal to the string length, the function returns a reference to a null character (charT()).
从实际测试来看,不仅仅是当str[pos]中的pos == str.length()时, 当其大于字符串长度时也是如此。虽然这样的过程是一番好意,但是有时候却让错误变得更难以发现,如下代码:
string a("abc"); string b(a); b.push_back(a[10]); cout<<a<<","<<b<<endl; cout<<(a == b)<<endl;
输出a, b时,他们是完全一样的,然而因为b比a多了NULL,在等值比较时就不相等了,非常令人困惑。当然根源还是,码农不小心。。。
第二轮:
居然写出如此冗长的代码,来个简短版的:
class Solution { public: string convert(string s, int numRows) { string res; if (numRows < 1) { return res; } vector<string> z(numRows); int len = s.size(); int row = 0; int delta = numRows == 1 ? 0 : 1; for (int i=0; i<len; i++) { z[row].push_back(s[i]); int next = row + delta; if (next == numRows || next == -1) { delta = -delta; } row += delta; } for (string& s : z) { res.append(s); } return res; } };
再来一个不用额外空间的
class Solution { public: string convert(string s, int numRows) { string res; if (numRows < 1) { return res; } int len = s.size(); if (len <= numRows || numRows == 1) { return s; } int delta = 2 * numRows - 2; for (int i=0; i<numRows; i++) { res +=s[i]; int next = i + delta; while (next - 2 * i < len) { if (i != 0 && i != numRows - 1) { res += s[next - 2 * i]; } if(next < len) { res += s[next]; } next += delta; } } return res; } };
快很多