The string
"PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)P A H N A P L S I I G Y I RAnd then read line by line:
"PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".
Analysis:
The idea is straightforward. Use a 2-D vector storing the zigzag sequence, for every element in the string, put it into proper position. Then output.
There are two major steps to put element into its position:
(1). Write # of nRows chars into the same column. like " | "
(2). Write # of nRows-2 chars into different column and rows in reverse diagonal order. like " / ".
e.g.
Input: PAYPALISHIRING
2D vector:
0 1 2 3 4 5 6 7
-------------------
0 | P I N
1 | A L S I G
2 | Y A H R
3 | P I
| / |
B D
There are two major steps to put element into its position:
(1). Write # of nRows chars into the same column. like " | "
(2). Write # of nRows-2 chars into different column and rows in reverse diagonal order. like " / ".
e.g.
Input: PAYPALISHIRING
2D vector:
0 1 2 3 4 5 6 7
-------------------
0 | P I N
1 | A L S I G
2 | Y A H R
3 | P I
(updated 201309):
Note: "ABCD" is A C| / |
B D
Code:
class Solution {
public:
string convert(string s, int nRows) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
vector<string> zz(nRows,"");
if (nRows==1){return s;}
int i=0; //for string
int r=0; //for zz vector
bool zig = false; // if s[i] is in "/" or "|" direction
while (i<s.size()){
if (r<nRows && !zig){
zz[r]+=s[i];
r++;
i++;
}else{
if (!zig){
zig=true;
r--;
}else{
r--;
zz[r] = zz[r]+s[i];
if (r==0){zig=false;r++;}
i++;
}
}
}
string res; //get result;
for (int i=0;i<zz.size();i++){
for (int j=0;j<zz[i].size();j++){
res = res+ zz[i][j];
}
}
return res;
}
};
(old version)Code:
class Solution {
public:
string printStr(vector<vector<char> > &t, int col,int nRow){
string str="";
for (int j=0;j<nRow;j++){
for (int i =0; i<=col;i++){
if (t[j][i]!='#'){
str = str+ t[j][i];
}
}
}
return str;
}
string convert(string s, int nRows) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if ((nRows<=0) || (s.size()==0)){return "";}
if (nRows==1) {return s;}
if (nRows>=s.size()){return s;}
int k=s.size();
vector<vector<char> > t(nRows,vector<char>(k,'#'));
int len = s.size();
int col = 0;
int row = 0;
int count = 0;
while(count < len){
if (row<nRows){
t[row][col]=s[count];
row++;
count++;
}else{
col++;
for (int j = nRows-2; j>=1;j--){
t[j][col]=s[count];
count ++;
if (count>=len){ return printStr(t,col,nRows);}
col++;
}
row = 0;
}
}
return printStr(t,col,nRows);
}
};
class Solution {
ReplyDeletepublic:
string convert(string s, int nRows) {
int n=s.size();
if(n==0) return "";
if(nRows==1)
return s;
int half = nRows-1;
int step = half*2;
string ret="";
vector v(nRows,"");
for(int i=0; i<n; i+=step)
{
for(int j=0; j<half; j++)
if(i+j<n) v[j]+=s[i+j];
for(int j=0; j<half; j++)
if(i+half+j<n) v[half-j]+=s[i+half+j];
}
for(int i=0; i<nRows; i++)
ret+=v[i];
return ret;
}
};
For this problem, using a little bit math to figure out the index increment of each row seems to provide a more simplified solution, here is my code (no need to maintain a 2D vector for storing intermediate results:
ReplyDeletestring convert(string s, int nRows) {
string res;
if(nRows==1) return s;
for(int i=0; i<nRows && i<s.size(); i++) {
int inc = 2*(nRows-i-1), cur = i, pre =-1;
while(cur<s.size()) {
if(cur!=pre) res.push_back(s[cur]);
pre = cur;
cur += inc;
inc = 2*(nRows-1)-inc;
}
}
return res;
}
thumbs up bro!!
Deletesame as I did.
Delete