这道题目,我一开始的解法太过复杂,虽然勉强可以AC,但是调试和维护什么的,都很费精力。想想还是自己的算法不够好,虽然非常细致、精细,但是实现起来,却过于复杂,不够简单。我写的代码如下:
string convert(string s, int numRows) {
if (numRows == 1) { // 特殊情况
return s;
}
int len, loop, loopTimes, i, cnt, index, tmp;
string result = "";
len = (int)s.length();
loop = 2*numRows - 2; // 一个循环的长度
loopTimes = len/loop;
for (i=0 ; i<numRows && i<len; i++) { // i<s.length() 避免越界
cnt = loopTimes-1;
index = i;
result += s.at(index);
if (i != 0 && i != numRows-1) { // 当i不为0且不为numRows-1时候,其下标增长情况为先加(1)loop-2*i后加(2)2*i。(1)、(2)交替增长。
while (cnt>0) {
cnt--;
index += loop - 2*i;
result += s.at(index);
index += 2*i;
result += s.at(index);
}
if (index+loop-2*i <= len-1) { // 增长(1)
index += loop - 2*i;
// cout << index << endl;
result += s.at(index);
if (index+2*i <= len-1) { // 增长(2)
index += 2*i;
result += s.at(index);
if (index+(loop-2*i) <= len-1) { // 增长(1)
index += loop-2*i;
result += s.at(index);
}
}
}
} else { // 当i为0或者numRows-1时
while (cnt>0) {
cnt--;
index += loop;
result += s.at(index);
}
if (index + loop <= len-1) {
result += s.at(index+loop);
}
}
}
return result;
}
后来找到别人写得代码,果然简单很多。我的算法的问题在于,没有充分利用到loop和loopLen。虽然意识问题的求解与loop息息相关,却没有用到太多。注意:想不明白边界条件的时候,不妨直接用if(边界为字符串长度len-1),这样就能把所有的出界情况全考虑到了。新的代码如下:
string convert(string s, int nRows) {
int firstIndex, reverseIndex, loopLen, len;
loopLen = nRows <= 1 ? nRows : (2 * nRows - 2);
len = (int)s.length();
string result = "";
for (int offset = 0; offset < nRows; offset++) {
for (int zigIndex = 0; zigIndex * loopLen < len; zigIndex++) { // <span style="color:#ff0000;">注意zigIndex从0开始。zigIndex的取值范围为0, 1,...len/loopLen</span>
firstIndex = zigIndex * loopLen + offset;
if (firstIndex < len)
result += s.at(firstIndex);
if (offset > 0 && offset < nRows - 1) {
reverseIndex = (zigIndex + 1) * loopLen - offset;
if (reverseIndex < len)
result += s.at(reverseIndex);
}
}
}
return result;
}