6. Z 字形变换
难度中等将一个给定字符串 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);
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3 输出:"PAHNAPLSIIGYIR"示例 2:
输入:s = "PAYPALISHIRING", numRows = 4 输出:"PINALSIGYAHRPI" 解释: P I N A L S I G Y A H R P I
示例 3:
输入:s = "A", numRows = 1 输出:"A"
思路:
定义一个最终字符串fin,定义numsRow个整数,分别代表各行头部指针,在fin中找出对应行位置,将指针指向对应位置,再讲s中的字符串按行顺序输入给fin即可
步骤:
1.根据每行元素个数,计算指针位置;
2.根据s[i]中元素所在位置,计算所在行,并使用指针赋值给fin,同时指针+1;
代码:
class Solution { public: //思路,定义一个一维数组,获取numRows个指针,分别指向每行的开始所对应的位置 //在对s遍历时,按顺序输入对应行就可以的到一个排序后的字符串。 string convert(string s, int numRows) { //fin申请空间与s相等; string fin; fin.assign(s); //根据规律,可以看为一个周期函数T; //i%T为其在周期中的位置,i/T为其所在周期 int T=(numRows-2)*2+2; //可以优化为(numRows-1)*2,计算机来说区别不大 //计算的到每行元素个数; 取4个指针指向开头,填满就行; vector<int> state; int length=0; int Tnum=s.size()/T; //完整周期数 int Cnum=s.size()%T; //多余字符个数 for(int i=0;i<numRows;i++){ int thelen=0; //此行长度; state.push_back(length); //计算该行长度是由于第0行和最后一行只有一个字符,所以单独计算; if(i==0) {thelen+=((Cnum!=0)?Tnum+1:Tnum);} else if(i==numRows-1) thelen=Cnum<numRows?Tnum:Tnum+1; else{ thelen+=Tnum*2; //个数先加上满周期有的,未满周期另外计算; if(Cnum<=numRows&&Cnum>=i+1) thelen+=1; else if(Cnum>numRows) thelen+=(T-i+1<=Cnum)?2:1; //T-i+1为如果未满周期右方第i行刚好为最后一个字符时的Cnum值 } length+=thelen; } for(int i=0;i<s.size();i++) { // 先判断为第几行,再存入数据; unsigned int row=0; row=(i+1)%T; //先判断是一个周期的第几个数 if(row>numRows) row=T-row+1; //原式row=T+1(将周期补全至下一个周期第一个数) - row(还有多少数)+1-1; else row-=1; fin[state[row]++]=s[i]; } return fin; } };