Z字型变换解法整理
public class Solution {
// 这是我第一次写的方法,太糟糕了TAT
// 在算法的中间出现问题,并且没有找到解决方法,故放弃
// public String convert(String s, int numRows) {
// if(numRows==0||s.isEmpty())
// return "";
// if (numRows==1)
// return s;
// List<StringBuilder> list = new ArrayList<StringBuilder>();
// for(int i=0;i<numRows;i++)
// list.add(new StringBuilder());
// int n=s.length();
// int flag=numRows+numRows-2;
// int firstLine = n/flag+1;
// int j=2;
// int left=0;
// int right=0;
// for(int i=0;i<firstLine;i++) {
// //问题出现在这,虚拟的结点如何添加?
// //复杂度也是O(n),没有必要用这个方法。
// list.get(0).append(s.charAt(i*flag));
// while(j<=numRows) {
// left = i*flag-j+1;
// right = i*flag+j-1;
// if(left>0 && left>(i*flag-numRows+1))
// list.get(j-1).append(s.substring(left, left+1));
// if(right<=(i*flag+numRows) && right<n)
// list.get(j-1).append(s.substring(right, right+1));
// j++;
// }
// j=2;
// }
// StringBuilder result = new StringBuilder();
// for(int i=0;i<numRows;i++)
// result.append(list.get(i));
// return result.toString();
// }
}
//官方给的下面这个方法和我想的类似,但是比我的简单多了,我是受之前回文字符的影响,总是想找中心
//这个方法不是固定中心,而是固定起点(第一行的元素)和终点(最后一行的元素)
//找到起点和终点的字符是很简单的,数学推导即可
//行0 中的字符位于索引 k(2⋅numRows−2) 处;
//行numRows−1 中的字符位于索引 k(2⋅numRows−2)+numRows−1 处;
//内部的行i中的字符位于索引k(2⋅numRows−2)+i以及(k+1)(2⋅numRows−2)−i处;
//时间复杂度:O(n)
public 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();
}
}
//另一种简单的方法
//要学会使用boolean变量,当问题有两种状态时,使用boolean可以变得简单
//比如Z字型存到序列中时,有自上向下遍历和自下向上遍历两种状态。
public 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);
//每到Z的转折处改变存入字符序列的顺序(抽象为向上和向下)
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();
}
}