题目链接: https://leetcode.com/problems/zigzag-conversion/
1. 题目介绍(之字形)
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)
【Translate】: 字符串“PAYPALISHIRING”在给定的行数上以之字形的方式书写,如下所示:(为了更好的可读性,您可能需要使用固定的字体来显示此模式) And then read line by line: "PAHNAPLSIIGYIR"
【Translate】: 按行读取 “PAHNAPLSIIGYIR”
Write the code that will take a string and make this conversion given a number of rows:
【Translate】: 编写代码,该代码将接受一个字符串,并根据给定的行数进行转换
测试用例:
约束:
2. 题解
2.1 从上到下 按列存储( StringBuffer[] )
??该题解来源于dylan_yu。其基本思想就是通过生成对应长度的StringBuffer[]去根据限定条件存储对应的字符。通过i++ 一直遍历到字符串结束,同时又通过nRows限制了每一列该存储的数据。vertically down负责筛选正常列中的数据,obliquely up负责筛选Z型中间的数据。
class Solution {
public String convert(String s, int nRows) {
char[] c = s.toCharArray();
int len = c.length;
StringBuffer[] sb = new StringBuffer[nRows];
System.out.println(sb.length);
for (int i = 0; i < sb.length; i++) sb[i] = new StringBuffer();
int i = 0;
while (i < len) {
for (int idx = 0; idx < nRows && i < len; idx++)
sb[idx].append(c[i++]);
for (int idx = nRows-2; idx >= 1 && i < len; idx--)
sb[idx].append(c[i++]);
}
for (int idx = 1; idx < sb.length; idx++)
sb[0].append(sb[idx]);
return sb[0].toString();
}
}
2.2 从上到下 按列存储( StringBuilder[] )
??与2.1中的思想一致,只不过将 StringBuffer[] 替换成了 StringBuilder[],两者功能相同,但是StringBuilder[]的速度要比StringBuffer[]快,但是安全性要低。
public String convert(String s, int numRows) {
if (numRows <=1 || s.length() <= numRows) return s;
StringBuilder[] sb = new StringBuilder[numRows];
for (int i = 0; i < sb.length; i++) sb[i] = new StringBuilder();
int curRow = 0;
boolean godown = false;
char[] charArray = s.toCharArray();
for (char c: charArray) {
sb[curRow].append(c);
if (curRow == 0 || curRow == numRows - 1) godown = !godown;
curRow += godown? 1: -1;
}
StringBuilder ret = new StringBuilder();
for (StringBuilder data: sb) ret.append(data);
return ret.toString();
}
2.3 Sort by Row – O(n)
??Solution中的Approach 1。从左到右遍历s,将每个字符附加到适当的行。可以使用两个变量跟踪适当的行:当前行和当前方向。只有当我们向上移动到最上面一行或向下移动到最下面一行时,当前的方向才会改变。
class Solution {
public String convert(String s, int numRows) {
if (numRows == 1) return s;
List<StringBuilder> rows = new ArrayList<>();
for (int i = 0; i < Math.min(numRows, s.length()); i++)
rows.add(new StringBuilder());
int curRow = 0;
boolean goingDown = false;
for (char c : s.toCharArray()) {
rows.get(curRow).append(c);
if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
curRow += goingDown ? 1 : -1;
}
StringBuilder ret = new StringBuilder();
for (StringBuilder row : rows) ret.append(row);
return ret.toString();
}
}
2.4 Visit by Row – O(n)
??Solution中的Approach 2。首先访问第0行中的所有字符,然后是第1行,然后是第2行,依此类推……;纯数学推理了。
class Solution {
public String convert(String s, int numRows) {
if (numRows == 1) return s;
StringBuilder ret = new StringBuilder();
int n = s.length();
int cycleLen = 2 * numRows - 2;
for (int i = 0; i < numRows; i++) {
for (int j = 0; j + i < n; j += cycleLen) {
ret.append(s.charAt(j + i));
if (i != 0 && i != numRows - 1 && j + cycleLen - i < n)
ret.append(s.charAt(j + cycleLen - i));
}
}
return ret.toString();
}
}
3. 可参考
[1] Java StringBuffer 和 StringBuilder 类 [2] [LeetCode]006. 之字折线转换
|