题目
URL:https://leetcode.com/problems/zigzag-conversion

解法
一、程序员
对于一个程序员来说,肯定是想模拟 ZigZag 的数组,再根据 ZigZag 的位置一行一行的输出。
ZigZag 模拟很简单,首先得出行数和列数,之后模拟 ZigZag 方式:先向下,后对角,都是遇到边界停下。
public String convert(String s, int numRows) {
if (numRows == 1) return s;
int step = 2 * numRows - 2;
int columnRows = (s.length() / step + 1) * (step / 2);
char[][] c = new char[numRows][columnRows];
int count = 0, i = 0, j = 0;
boolean isDown = true;
while (count < s.length()) {
c[i][j] = s.charAt(count);
count++;
if (i == numRows - 1) {
isDown = false;
} else if (i == 0) {
isDown = true;
}
if (isDown) {
i++;
} else {
i--;
j++;
}
}
StringBuilder result = new StringBuilder();
for (int row = 0; row < c.length; row++) {
for (int col = 0; col < c[0].length; col++) {
if (c[row][col] != '\u0000') result.append(c[row][col]);
}
}
return result.toString();
}
程序员,时间复杂度O(n2),运行时间约为 90 ms。
二、数学家
必然有规律可以输出。
首先观察分组,每组数量是 2 * numRows - 2,对应的是一个纵列和对角列(当然不包括下一个纵列的头)。
其次观察分对,在分组中可以发现,第一个元素没有配对;第二个元素和倒数第一个元素配对;第三个元素和倒数第二个元素配对;······;中间有个元素,即 numRows -1 行的元素,是没有配对的,直接输出。
上面的思想完成之后,就可以具体实现:
- 输出第一列;
- 确定每个分组中每个分对的起始下标,输出分对元素;
- 输出最后一列。
public String convert(String s, int numRows) {
if (numRows == 1) return s;
int step = 2 * numRows - 2;
StringBuilder result = new StringBuilder();
for (int i = 0; i < s.length(); i += step) {
result.append(s.charAt(i));
}
for (int line = 1; line < numRows - 1; line++) {
for (int i = line; i < s.length(); i = i + step) {
result.append(s.charAt(i));
if (i + (numRows - line - 1) * 2 < s.length()) {
result.append(s.charAt(i + (numRows - line - 1) * 2));
}
}
}
for (int i = numRows - 1; i < s.length(); i += step) {
result.append(s.charAt(i));
}
return result.toString();
}
数学家,时间复杂度O(n2),运行时间约为 40 ms。
总结
程序员会数学真的是要上天。程序员应该学好数学,数学是计算机的基础。利用数学相关知识,可以优化程序性能。
来源:https://www.cnblogs.com/Piers/p/7153001.html