class Solution {
public String convert(String s, int numRows) {
if (numRows == 1){
return s;
}
int rowMax = Math.min(numRows, s.length());
List<StringBuilder> rows = new ArrayList<>();
for (int i = 0; i < rowMax; i++)
rows.add(new StringBuilder());
int curRow = 0;
int direction = -1;
for (char c : s.toCharArray()) {
rows.get(curRow).append(c);
if (curRow == 0 || curRow == numRows - 1){
direction *= -1;
}
curRow += direction;
}
StringBuilder ans = new StringBuilder();
for (StringBuilder row : rows) ans.append(row);
return ans.toString();
}
}
按题意模拟Z字形的过程,枚举每一行,到头了变方向,按顺序把字符加入对应的行,最后把每一行的字符拼起来。这里注意以下几点:
这里的时间复杂度为O(n),但是最后需要一行一行地拼起来,所以很慢。因此可以想到,把每一行字符在原字符串中的位置之间算出来,这样就可以按顺序添加,而非模拟Z字形再拼接。
class Solution {
public String convert(String s, int numRows) {
if (numRows == 1){
return s;
}
int n = s.length();
StringBuilder ans = new StringBuilder();
int num = 2 * numRows - 2;
for (int i = 0; i < numRows; i++) {
int del =num - 2 * i;
for (int j = i; j < n; j += num) {
ans.append(s.charAt(j));
if (i != 0 && i != numRows - 1 && j + del < n)
ans.append(s.charAt(j + del));
}
}
return ans.toString();
}
}
可以将一个来回视为一组,除了首行和末行,每组都有两个字符。
显然第i行的第一个字符是原字符串中的第i个字符。之后仅需计算组内两个字符的距离,以及组间的距离即可。
因为是按行数一来一回,所以显然每组的第一个字符之间的距离是2 * numRows - 2。
组内,按照Z字形的规律,第一个字符到第二个字符,显然是从下一组第一个字符往回走2*i。
有了这样的规律,我们一次添加一组的两个字符即可。
这样虽然时间复杂度仍为O(n),中间也略有计算,但总体来说,直接计算出下一个字符的位置,是快于多行拼凑的。
原文:https://www.cnblogs.com/xiafrog/p/14300652.html