问题描述:
将一个给定字符串 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);
解题思路:
利用二维矩阵模拟。
分治法,以组为单位填充矩阵,再顺序遍历矩阵拼接字符串,得到变换后的字符串。
此题简单,不用数学的方式,用模拟的方式,构造一个二维数组,模拟这个过程即可。
就是这个代码写起来有点小多而已。
代码如下:
class Solution {
//此题简单,不用数学的方式,用模拟的方式,构造一个二维数组,模拟这个过程即可。
//分治法
//以组为单位填写
public void fillArray(String s,char[][] strArray,int n,int m,int starti,int startj,int idx){
for(int i=0;i<=n-1 && idx<=s.length()-1;i++){
strArray[starti][startj]=s.charAt(idx);
idx++;
starti++;
}
starti=n-2;
startj++;//调到下一列
for(int i=1;i<=n-2 && idx<=s.length()-1;i++){
strArray[starti][startj]=s.charAt(idx);
idx++;
starti--;
startj++;
}
}
public String extract(char[][] strArray,int n,int m){
StringBuffer result=new StringBuffer();
for(int i=0;i<=n-1;i++){
for(int j=0;j<=m-1;j++){
if(strArray[i][j]!='#'){
result.append(strArray[i][j]);
}
}
}
return result.toString();
}
public String convert(String s, int numRows) {
//Rows 1,1到nums-2..交替循环
if(numRows==1){//特殊处理
return s;
}
int groups=s.length()/(numRows+numRows-2);
int remains=s.length()-groups*(numRows+numRows-2);
int columns=groups*(numRows-1);
if(remains>0){
if(remains<=numRows){
columns+=1;
}else{
columns+=1+remains-numRows;//1列+中间剩余多少字符
}
groups++;
}
char[][] strArray=new char[numRows][columns];
//初始化二维数组
for(int i=0;i<=numRows-1;i++){
for(int j=0;j<=columns-1;j++){
strArray[i][j]='#';//初始符号代表空
}
}
int starti=0,startj=0;
for(int i=0;i<=groups-1;i++){
fillArray(s,strArray,numRows,columns,starti,startj,i*(numRows+numRows-2));
starti=0;
startj+=numRows-1;
}
// //输出二维数组
// for(int i=0;i<=numRows-1;i++){
// StringBuffer str1=new StringBuffer();
// for(int j=0;j<=columns-1;j++){
// str1.append(strArray[i][j]);
// }
// System.out.println(str1);
// }
return extract(strArray,numRows,columns);
}
}
这道题时间和内存空间都是有优化空间的。