每日一题06:Z 字形变换

每日一题06:Z 字形变换

题目:

将一个给定字符串根据给定的行数,以从上往下、从左到右进行Z 字形排列。

输入: s = "LEETCODEISHIRING", numRows =4

输出:"LDREOEIIECIHNTSG"

解释:

L D R

E O E I I

E C I H N

T S G

算法:

每日一题06:Z 字形变换

每日一题06:Z 字形变换

解法:

方法一:把所有字符遍历放入数组中,对数组重新组合

public String convert(String s, int numRows) {
\t\tif(s.length() == 0){
return "";
}
\t\tif(numRows == 1){
\t\t\treturn s;
\t\t}
\t\tint h = s.length() / (numRows-1);
\t char[][] a = new char[numRows][h*(numRows-1)+1];
\t int n = 0;
\t for(int i=0;i\t \tif(i%(numRows-1) == 0){

\t\t \tfor(int j=0;j<numrows>\t\t \t\tif(n >= s.length()){
\t\t \t\t\tbreak;
\t\t \t\t}
\t\t \t\ta[j][i] = s.charAt(n);
\t\t \t\tn++;
\t\t \t}
\t \t}else{
\t \t\tif(n >= s.length()){
\t \t\t\tbreak;
\t \t\t}
\t \t\ta[numRows-1-i%(numRows-1)][i] = s.charAt(n);
\t \t\tn++;
\t \t}
\t }
\t char[] b = new char[s.length()];
\t int count = 0;
\t for(int i=0;i<numrows>\t \tSystem.out.println(String.valueOf(a[i]));
\t \tfor(int j=0;j\t \t\tif(a[i][j] != '\\0'){
\t \t\t\tif(count >= s.length()){
\t \t\t\t\tbreak;
\t \t\t\t}
\t \t\t\tb[count] = a[i][j];
\t \t\t\tcount++;
\t \t\t}
\t \t}
\t }
\t
\t System.out.println(String.valueOf(b));
\t\treturn String.valueOf(b);
}
/<numrows>/<numrows>

方法二:通过从左向右迭代字符串,我们可以轻松地确定字符位于 Z 字形图案中的哪一行。

String convert2(String s, int numRows) {

\t\t if (numRows == 1) return s;

\t List<stringbuilder> rows = new ArrayList<stringbuilder>();
\t for (int i = 0; i < Math.min(numRows, s.length()); i++)
\t rows.add(new StringBuilder());

\t int curRow = 0;
\t boolean goingDown = false;

\t for (char c : s.toCharArray()) {
\t rows.get(curRow).append(c);
\t if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
\t curRow += goingDown ? 1 : -1;
\t }

\t StringBuilder ret = new StringBuilder();
\t for (StringBuilder row : rows) ret.append(row);
\t return ret.toString();
\t}/<stringbuilder>/<stringbuilder>

方法三:每一行字母的所有下标其实是有规则的

我们先假定有 numRows=4 行来推导下,其中 2*numRows-2 = 6 , 我们可以假定为 step=2*numRows-2 ,我们先来推导下规则:

第0行: 0 - 6 - 12 - 18

==> 下标间距 6 - 6 - 6 ==> 下标间距 step - step - step

第1行: 1 - 5 - 7 - 11 - 13

==> 下标间距 4 - 2 - 4 - 2 ==> 下标间距step-2*1(行)-2*1(行)-step-2*1(行)-2*1(行)

第2行: 2 - 4 - 8 - 10 - 14

==> 下标间距 2 - 4 - 2 - 4 ==> 下标间距step-2*2(行)-2*2(行)-step-2*2(行)-2*2(行)

第3行:3 - 9 - 15 - 21

==> 下标间距间距 6 - 6 - 6 ==>下标间距step - step - step

可以得出以下结论:

起始下标都是行号

第0层和第numRows-1层的下标间距总是step 。

中间层的下标间距总是step-2*行数,2*行数交替。

下标不能超过len(s)-1

String convert1(String s, int numRows) {
\t\tif (numRows == 1) return s;

\t\tint step = numRows * 2 - 2; // 间距
\t\tint index = 0;// 记录s的下标
\t\tint len = s.length();
\t\tint add = 0; // 真实的间距
\t\tString ret = "";
\t\tfor (int i = 0; i < numRows; i++) // i表示行号
\t\t{
\t\t\tindex = i;
\t\t\tadd = i * 2;
\t\t\twhile (index < len)//超出字符串长度计算下一层
\t\t\t{
\t\t\t\tret += s.charAt(index); // 当前行的第一个字母
\t\t\t\tadd = step - add;// 第一次间距是step -2*i,第二次是2*i,
\t\t\t\tindex += (i == 0 || i == numRows-1) ? step : add; // 0行和最后一行使用step间距,其余使用add间距
\t\t\t}
\t\t}
\t\treturn ret;
\t}


分享到:


相關文章: