要求:
一开始看到题目,第一想到的思路,就被题目要求的思路给带偏了。
内容是Z字型输出内容
就一直想着把字符串输出成上面这种格式
总是想着把字符串放入到二维数组中进行展示。
这样一来思路就受到了限制。
一直使用先写入数组中。
//将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
//比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
public static String convert1(String s, int numRows) {
System.out.println("s.length="+s.length());
//想法和思路。Z字格设计,其实就是把数字一个个放进到二维数组中。再按照顺序去读取出来。
//二维 数组的长度length=s.length/(width-1),width=numRows
int arr_width = numRows;
int arr_length = s.length()/(arr_width-1);
int lie_mark=0;//向右进位标记
int hang_mark=0;//向下进位标记
//根据长度进行生成数组
int[][] arrays = new int[arr_width][arr_length];
//因为Z字写入数据,需要反向写入数据,涉及到了标记。
int flag =-1;//flag==1,则从上往下写。 flag==-1,从下往上写。
// i=0 ,1,2 i=3反向 i=5反向 i =9
int flag_count =0;
//记录结果
int result=0;
if(numRows==1){
return s;
}else {
for (int i = 0; i < s.length(); i++) {
hang_mark=flag_count;
// System.out.println("i="+i);
// System.out.println("lie_mark="+lie_mark);
// System.out.println("hang_mark="+hang_mark);
arrays[hang_mark][lie_mark]=s.charAt(i);
if(flag_count==0 && flag_count==numRows-1){
flag=-flag;//反向
}
//判断什么时候往下写
if(flag==1){//向下输出
flag_count++;
}
//判断什么时候向上斜写,(x+1)(y-1)
if(flag==-1){//向上输出
flag_count--;
lie_mark++;
}
System.out.println("flag_count="+flag_count);
}
}
//测试遍历二维数组
for (int i = 0; i < arr_length; i++) {
for (int j = 0; j < arr_width; j++) {
System.out.print(" " +String.valueOf(arrays[i][j]));
}
System.out.println('\n');
}
return "";
}
该功能还没写完,还存在测BUG.有待完善。
而在后续中,又想到一种办法,那就是不去一个个的写入。直接由果推导因。
我们的最终结果是字符串形式,那么我们就直接用字符串去进行拼接就行。
public static String convert(String s, int numRows) {
//用于接收字符串组
StringBuilder[] results = new StringBuilder[numRows];
//String对象赋值
for (int i = 0; i < numRows; i++) {
results[i]=new StringBuilder();
}
//反向输出标志:
int flag_count=0;//反向计数器。=0或者=numRows-1的时候说明到顶和底了,可以反向
int flag = -1;// =1向下输出,=-1向上输出
//判空
if(numRows==1) return s;
for(int i=0;i<s.length();i++){
//按照结果意愿来进行存放
results[flag_count].append(s.charAt(i));
//判断顶底,进行反向输出
if(flag_count==0 || flag_count==(numRows-1))
flag=-flag;
//计数器工作,每次循环计数一次
if(flag==1)
flag_count++;//=0向下输出
else
flag_count--;//=1向上输出
}
StringBuilder display = new StringBuilder();
for (int i = 0; i < numRows; i++) {
display.append(results[i].toString());
}
return display.toString();
}
下面是调试的字符串结果:
算法解释:
1.根据flag来进行判断向上输出还是向下输出
2.根据flag_count来判断顶底,到了顶底进行反向。
附上所有的代码:
package com.zhm.test;
/**
* @Author bige
* @Date: 2022/11/28 10:37
* @ApiNote:Z 字形变换
*/
public class Leetcode_test006 {
//将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
//比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
public static String convert1(String s, int numRows) {
System.out.println("s.length="+s.length());
//想法和思路。Z字格设计,其实就是把数字一个个放进到二维数组中。再按照顺序去读取出来。
//二维 数组的长度length=s.length/(width-1),width=numRows
int arr_width = numRows;
int arr_length = s.length()/(arr_width-1);
int lie_mark=0;//向右进位标记
int hang_mark=0;//向下进位标记
//根据长度进行生成数组
int[][] arrays = new int[arr_width][arr_length];
//因为Z字写入数据,需要反向写入数据,涉及到了标记。
int flag =-1;//flag==1,则从上往下写。 flag==-1,从下往上写。
// i=0 ,1,2 i=3反向 i=5反向 i =9
int flag_count =0;
//记录结果
int result=0;
if(numRows==1){
return s;
}else {
for (int i = 0; i < s.length(); i++) {
hang_mark=flag_count;
// System.out.println("i="+i);
// System.out.println("lie_mark="+lie_mark);
// System.out.println("hang_mark="+hang_mark);
arrays[hang_mark][lie_mark]=s.charAt(i);
if(flag_count==0 && flag_count==numRows-1){
flag=-flag;//反向
}
//判断什么时候往下写
if(flag==1){//向下输出
flag_count++;
}
//判断什么时候向上斜写,(x+1)(y-1)
if(flag==-1){//向上输出
flag_count--;
lie_mark++;
}
System.out.println("flag_count="+flag_count);
}
}
//测试遍历二维数组
for (int i = 0; i < arr_length; i++) {
for (int j = 0; j < arr_width; j++) {
System.out.print(" " +String.valueOf(arrays[i][j]));
}
System.out.println('\n');
}
return "";
}
// 例如对一个4行的
//
// 0 6 12 18
// 1 5 7 11 13 17
// 2 4 8 10 14 16
// 3 9 15
//
// 对于n行的, s中的第i个字符:lie=i%(numrows-1).
// 对余数进行判断
// i%(2n-2) == 0 ----> row0
// i%(2n-2) == 1 & 2n-2-1 ----> row1
// i%(2n-2) == 2 & 2n-2-2 ----> row2
// i%(2n-2) == 3
// ...
// i%(2n-2) == n-1 ----> row(n-1)
// ==>
// 对 k = i%(2n-2)进行判断
// k<=n-1时候,s[i]就属于第k行
// k>n-1时候,s[i]就属于2n-2-k行
// 最后将rows拼接起来就行了
public static String convert(String s, int numRows) {
//用于接收字符串组
StringBuilder[] results = new StringBuilder[numRows];
//String对象赋值
for (int i = 0; i < numRows; i++) {
results[i]=new StringBuilder();
}
//反向输出标志:
int flag_count=0;//反向计数器。=0或者=numRows-1的时候说明到顶和底了,可以反向
int flag = -1;// =1向下输出,=-1向上输出
//判空
if(numRows==1) return s;
for(int i=0;i<s.length();i++){
//按照结果意愿来进行存放
results[flag_count].append(s.charAt(i));
//判断顶底,进行反向输出
if(flag_count==0 || flag_count==(numRows-1))
flag=-flag;
//计数器工作,每次循环计数一次
if(flag==1)
flag_count++;//=0向下输出
else
flag_count--;//=1向上输出
}
StringBuilder display = new StringBuilder();
for (int i = 0; i < numRows; i++) {
display.append(results[i].toString());
}
return display.toString();
}
// 0 6 12 18
// 1 5 7 11 13 17
// 2 4 8 10 14 16
// 3 9 15
public static void main(String[] args) {
//String s = "0123456789876543210";
String s = "PAYPALISHIRING";
//convert(s,3);
System.out.println("result = " + convert1(s,3));
}
}