本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41408021
看完这篇文章,你可能会学到到知识如下:
(1)对于给定的算法题,如何正确对其进行分析,而不是通过穷举的方式来得到答案。(2)当解题逻辑非常清晰时,才开始编码,否则你很难编写出正确的代码。
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"
.
思路:
(1)通过字符串在每一行出现的顺序,可以其分两个部分:第一行和最后一行,中间行。
(2)对于第一行和最后一行,由上图可知,具有相同的对应关系。
(3)对于中间行,前一个下标的值和后一个下标的值需要根据这个下标是该行中的奇数列还是偶数列来计算。
(4)对已第一行和最后一行,通过规律发现,其对应关系为:start + 2 * 总行数 - 2 ,其中start为该行起始字符在数组的位置。例如第一行开始的start = 0,则后续对
应位置 为0 + 2 * 5 - 2 = 8,初始start为各行的起始值。同理,对于最后一行,当start = 4时,则后续对应位置为4+ 2 * 5 - 2 = 12,依此类推。
(5)对于中间行,当列数为奇数时,其对应位置关系为:start + 2 * (总行数 - 当前行 - 1);当列数为偶数时,其对应关系为:start + 2 * 当前行,其中当前列从0开始
。例如,对于第三行的起始start = 3,其后续位置所在列为1,是奇数列,则后续位置为 3 + 2 * (5 - 3 -1)= 5 ,此时start = 5,则其后续位置所在列数为4,是偶数
列,则后续位置为5 + 2 * 3= 11。
这道题有点类似数学中的归纳和总结相关的题目,其考的不是编程的技巧,而是通过发现规律,并对其进行分析,从而达到解题的目的。总体上感觉,要想算法比较好,扎实的数
学功底很有必要,所以,在业余时间,多花时间学数学也是很有必要的。这里推荐几本和计算机相关的数学书籍:《程序员的数学》、《具体数学》、《质数的孤独》。希望对你
有所帮助,也希望大家分享各自的学习心得和体会。
解题代码如下:
public static String convert(String s, int nRows) {
if (nRows <= 0)
return "";
if (nRows == 1 || nRows >= s.length())
return s;
StringBuffer buffer = new StringBuffer();
int len = s.length();
for (int i = 0; i < len && i < nRows; ++i) {
// 在字符串中的变化的位置
int start = i;
buffer.append(s.charAt(start));
for (int j = 1; start < len; ++j) {
// 第一行和最后一行
if (i == 0 || i == nRows - 1) {
start = start + 2 * nRows - 2;
} else {
// 对于中间行,在字符串中位置为基数时
if (j % 2 == 1) {
start = start + 2 * (nRows - i - 1);
} else {
// 位置为偶数时
start = start + 2 * i;
}
}
// 边界判断
if (start < len)
buffer.append(s.charAt(start));
}
}
return buffer.toString();
}