题目描述##
解题思路
题意不难理解,就是是把输入的字符串上下上下走之字形状,然后按行输出,起初打算用二维数组来存储字符串,参数中的nRows作为二维数组的行,那接下来要考虑的就是如何将字符和二维数组的下标对应起来,这是问题的关键,而解决该问题的突破口就是找规律,但转念一想,既然是找规律,何不观察输入字符串的字符下标按照题示要求排列后所处位置的规律呢,这样的话也不用去申请那么大一个二维数组了。于是我分别取nRows为2,3,4,5去寻找其排列规律:
通过细心观察字符串在每一行出现的顺序发现如下规律:
1.对已第一行和最后一行,其对应关系为:start + 2 * nRwos - 2 ,其中start为该行起始字符在数组的位置。例如nRwos取5时第一行开始的start = 0,则后续对应位置 为0 + 2 * 5 - 2 = 8,初始start为各行的起始值。同理,对于最后一行,当start = 4时,则后续对应位置为4+ 2 * 5 - 2 = 12,依此类推。
2.对于中间行,当列数为奇数时,其对应位置关系为:start + 2 * (nRows - 当前行 - 1);当列数为偶数时,其对应关系为:start + 2 * 当前行。
所以思路渐渐清晰起来,用for循环遍历每一行字符,对于每一行,根据某字符所在的行与列来根据上面的规律得出该字符在输入字符串中的下标,如果不越界,则将其加入到输出字符串当中。
C++实现
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1 || numRows >= s.length())
return s;
string result;
int len = s.length();
for (int i = 0; i < len && i < numRows; ++i) {
// 在字符串中的变化的位置
int start = i;
result += s[start];
for (int j = 1; start < len; ++j) {
if (i == 0 || i == numRows - 1) {
start += 2 * numRows - 2;
} else {
// 对于中间行,在字符串中位置为基数时
if (j % 2 == 1) {
start += 2 * (numRows - i - 1);
} else {
// 位置为偶数时
start += 2 * i;
}
}
// 边界判断
if (start < len)
result += s[start];
}
}
return result;
}
};
运行截图
反思与总结
这道题目与之前做过的一些不同,通过细心观察排列规律就可得出解题思路,难度一般,不过还是有不一样的收获。
update:
再次遇到这题,压根是换了另一个套路找规律。。。
首尾两行下标增加的规律是oneAdd = 2 * numRows - 2
而中间第i行下标增加的规律是first[i]、oneAdd-first[i]、first[i]、…
至于first[i]同样也是有规律的 这个可以请读者自行探寻~
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1) return s;
// 找规律
int oneAdd = 2 * numRows - 2; // 第1和第numRows行下标都是加oneAdd
int tmp = oneAdd;
vector<int> first(numRows+1, oneAdd);// 第i行中间都是依次加first[i]、oneAdd-2、first[i]、oneAdd-2
for (int i = 2; i <= numRows-1; ++i) {
first[i] = tmp - 2;
tmp -= 2;
}
string res = "";
int index = 0;
// 加第一行
while (index < s.size()) {
res += s[index];
index += oneAdd;
}
// 加中间行
index = 1;
for (int row = 2; row <= numRows-1; ++row) {
while (index < s.size()) {
res += s[index];
index += first[row];
if (index < s.size()) {
res += s[index];
index += (oneAdd - first[row]);
}
}
index = row + 1 - 1;
//cout << index << " " << s[index] << endl;
}
// 加最后一行
index = numRows - 1;
while (index < s.size()) {
res += s[index];
index += oneAdd;
}
return res;
}
};
LeetCode result:faster than 94.66% of C++ online submissions for ZigZag Conversion.