解法一:
暴力法,把整个图形分成最后一个图形和剩下的图形,每个图形分为第一列和剩下的列,找规律编程。
图中每一个对勾是一个图形
找bug找了好久好久,最后提交的时候还因为开的数组A的大小不合适,导致数组下边越界或者超时,试了几次竟然试出来了合适的大小…… 感觉自己真是个老实人。
这种解法其实挺不好的,下边有一个好方法。
class Solution {
public:
string convert(string s, int numRows) {
string sresult;
if (s==""){
sresult="";
return sresult;
}
else if(s.length()==1){
return s;
}
else if(numRows==1){
return s;
}
int len=s.length(),still_left;
int Num_of_fi=(len%(2*numRows-2)==0)?len/(2*numRows-2):len/(2*numRows-2)+1; //图形的数量
int k=0,left=0,right;
char A[1000][5000];
for(int i=0;i<numRows;i++){
for(int j=0;j<5000;j++){
A[i][j]='*';
}
}
for(int n1=0;n1<Num_of_fi;n1++){
if(n1!=0){
left=left+numRows-1;
}
right=left+numRows-2;
if(n1==Num_of_fi-1){ //最后一个图形,不一定会所有位置填满
still_left= len-(2*numRows-2)*(Num_of_fi-1); //还剩still_left个字符没放
if(still_left<=numRows){
int i=0;
while(still_left--){
A[i++][left]=s[k++];
}
}
else{
for(int i=0;i<numRows;i++){ //该图形的第一列
A[i][left]=s[k++];
}
still_left-=numRows;
right=left+still_left;
for(int y1=left+1;y1<=right;y1++){ //每个图形的后几列
int x1=left+numRows-1-y1;
A[x1][y1]=s[k++];
}
}
}
else{ //不是最后一个图形
for(int i=0;i<numRows;i++){ //每个图形的第一列
A[i][left]=s[k++];
}
for(int y1=left+1;y1<=right;y1++){ //每个图形的后几列
int x1=right+1-y1;
A[x1][y1]=s[k++];
}
}
}
int loca=0;
for(int i=0;i<numRows;i++){
for(int j=0;j<=right;j++){
if(A[i][j]!='*'){
sresult+=A[i][j];
}
}
}
return sresult;
}
};
解法二:
真是太不会变通了。题目说是Z字形,也不能真的非是Z字形啊,重点得看题目要干嘛,题目说让他按Z字形排列,最后输出的是另一个维度的排列好的顺序。所以只要有另一个维度的顺序就好。分析发现,Z字形排列,可以定义一个有numRows行的rows,每一行是一个字符串。将s中的字符按照从上往下,在从下往上,从上往下,直到所有的字符都放进rows为止,然后再从上往下遍历rows的每一行,输出就是答案。
class Solution {
public:
string convert(string s, int numRows) {
if (s.length()==1||s.length()==0){
return s;
}
else if(numRows==1){
return s;
}
vector<string> result(numRows);
int director=-1; //director表示当前遍历方向,1为向下,-1为向上
int current=0;
for(char c : s){
result[current]+=c;
if(current==0 || current==numRows-1){ //是第一行或者最后一行,要翻转遍历方向
director=-director;
}
current+=director;
}
string output;
for(string row :result){
output+=row;
}
return output;
}
};