题目描述:
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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
解析:
这个 Z 字型其实是这样的:
对于前面的 3 行的 示例1 , 它的字符数分布是这样的:
对于前面的 4 行的 示例2 , 它的字符数分布是这样的:
那么对于 n 行的字符数分布是这样的:
如上图所示,我们可以发现:
向下箭头的每个列有n个字符,向右上箭头的有(n-2)个字符。
由此我们知道,
向下箭头中每个列的字符在原字符串中的下标为:0—(n-1)
向右上箭头的每个列的字符在原字符串中的下标为:n—(2n-3).
(PS:此处一定要理解这个(2n-3)是怎么来的)
由此可见:
1.当前行 curRow 为 0 或 n-1 时,箭头发生反向反转。
从左到右按箭头方向迭代 s ,将每个字符添加到合适的行。之后从上到下遍历行即可。
我们假定 n=numRows :
import org.apache.commons.lang3.StringUtils;
/**
* Created by Bruce on 2020/7/23
**/
public class Test{
String convert(String s, int numRows) {
if(StringUtils.isBlank(s) || numRows <= 0){
return null;
}
if(numRows == 1){
return s;
}
int len = Math.min(s.length(), numRows);//防止s的长度小于行数
String[] chars = new String[len];//新生成的数组,每个字符串存放一行数据
for(int i = 0; i < len; i++){
chars[i] = "";
}
int loc = 0;
Boolean down = false;//默认箭头是向下的
for(int i = 0; i < s.length(); i++){
chars[loc] = chars[loc] + s.substring(i, i+1);
if(loc == 0 || loc == numRows - 1){//当当前行loc为0或(numRows-1)时,箭头发生反转
down = !down;
}
//如果当前箭头向下则新数组下标+1,如果当前箭头向右则下标-1;结合上图理解。
loc = loc + (down ? 1 : -1);
}
String res = "";
for(String string : chars){
res = res + string;
}
System.out.println(res);
return res;
}
public static void main(String[] args) {
Test6Zzxbh test = new Test6Zzxbh();
test.convert("LEETCODEISHIRING",3);
}
}