题目
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。
总结
程序员会数学真的是要上天。程序员应该学好数学,数学是计算机的基础。利用数学相关知识,可以优化程序性能。