将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:
L D R
E O E I I
E C I H N
T S G
思路:关键是找出同一行的字符之间的序列关系
0 2R-2
1 2R-4 2R-2
2 2R-6 2R-2
... ... ...
n 2R-2
第一行和最后一行可以单独拿出来处理
1 class Solution { 2 public: 3 string convert(string s, int numRows) { 4 int n=s.size(); 5 if(n==0||numRows==0)return ""; 6 if(numRows==1) return s; 7 string sz=""; 8 for(int i=0;i<numRows;i++)//2行及以上的 9 { 10 if(i!=0&&i!=(numRows-1)) 11 { 12 if(i<n) 13 sz+=s[i]; 14 else break; 15 for(int d=1,k=0,m=1;;k++,m++) 16 { 17 if((i+d*(2*numRows-2*i-2)+k*(2*numRows-2))<n) 18 { 19 sz+=s[i+d*(2*numRows-2*i-2)+k*(2*numRows-2)]; 20 } 21 else break; 22 if((i+m*(2*numRows-2))<n) 23 sz+=s[i+m*(2*numRows-2)]; 24 else break; 25 } 26 } 27 else 28 { 29 //第一行和最后一行的 30 for(int k=0;;k++) 31 { 32 if((i+(2*numRows-2)*k)<n) 33 sz+=s[i+(2*numRows-2)*k]; 34 else break; 35 } 36 } 37 } 38 return sz; 39 } 40 };
更简便的方法:
思路:创建个容器,vector<string>类型,容器大小为min(行数,字符串大小),容器每个元素保存一行的字符序列。遍历字符串,根据Z字形的方向确定字符放进哪个元素,遍历完后把所有元素的字符串加起来即为答案。技巧:通过一个标志来确定方向。
1 class Solution { 2 public: 3 string convert(string s, int numRows) { 4 5 if (numRows == 1) return s; 6 7 vector<string> rows(min(numRows, int(s.size()))); 8 int curRow = 0; 9 bool goingDown = false; 10 11 for (char c : s) { 12 rows[curRow] += c; 13 if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown; 14 curRow += goingDown ? 1 : -1; 15 } 16 17 string ret; 18 for (string row : rows) ret += row; 19 return ret; 20 } 21 };
原文:https://www.cnblogs.com/cs0915/p/12770639.html