将一个给定字符串s根据给定的行数numRows ,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
P A H N A P L S I I G Y I R
之后,输出需要从左往右逐行读取,产生出一个新的字符串如:"PAHNAPLSIIGYIR"。请实现这个将字符串进行指定行数变换的函数:string convert(string s, int numRows);
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"
方法一:按行排序
从左向右迭代字符串,从来确定字符位于Z字形图案中的哪一行。可以使用min(numRows,len(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 goingDpwn=false;
for(char c:s.toCharArray()){
rows.get(curRow).append(c);
if(curRow==0||curRow==numRows-1) goingDpwn=!goingDown;
curRow+=goingDown ? 1 : -1;
}
StringBuilder ret=new StringBuilder();
for(StringBuilder row:rows) ret.append(row);
return ret.toString();
}
}
方法二:按行访问
按照与逐行读取Z字形图案相同的顺序访问字符串。
首先访问行0中所有字符,接着访问行1,然后行2,依次类推..对于所有整数k,
行0中的字符位于索引k(2*numRows-2)处;
行numRows-1中的字符位于索引k(2*numRows-2)+numsRows-1处;
内部的行i中的字符位于索引k(2*numRows-2)+i以及(k+1)(2*numRows-2)-i处;
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();
}
}