算法-Z字形变换
1、Z字形变换
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:
L D R
E O E I I
E C I H N
T S G
这个题目如果方法想对了就比较简单,如果想不对,那就很绕了。看到这个题目我们可能首先会想到找规律,不过,找规律并不是一件简单的事情,可能会带来很多麻烦。
这就需要我们转变思路,我们需要一层一层的剥开这个字符串。如果横着剥开,那就是数学法,找通项公式,如果竖着按列剥开,事情就简单了很多,我们在按列读取的时候,可以为每一行维护一个字符串,读到哪一行就在后面append字串。
判断在哪一行append字串的方式也很简单,我们设置两个边界,在增长到或者减小到某个边界的时候,读取行的顺序进行反转,不断地从上到下,再从下到上读取,直到取完所有字串。
按照上面的描述,我们就可以得到这样的代码,写的比较清晰了,不在多做解释。
public String convert(String s, int numRows) {
if(s==null||s.length()==0||numRows<=1||s.length()<numRows){
return s;
}
StringBuilder[] sbs=new StringBuilder[numRows];
for(int i=0;i<numRows;i++){
sbs[i]=new StringBuilder();
}
int layer=0;
boolean turn=false;
for(int i=0;i<s.length();i++){
if(!turn){
sbs[layer++].append(s.charAt(i));
}else{
sbs[layer--].append(s.charAt(i));
}
if(layer==-1||layer==numRows){
layer=layer==-1?1:layer-2;
turn=!turn;
}
}
StringBuilder result=new StringBuilder();
for(StringBuilder sb:sbs){
result.append(sb.toString());
}
return result.toString();
}