思路
创建一个二维字符数组,相当于一张表,按照他的存储方式存进去,最后用行优先遍历获得新字符串
源码:
class Solution {
public:
string convert(string s, int numRows) {
char carr[numRows][1000];
for(int x = 0;x < numRows;x++){
for(int k = 0;k<1000;k++){
carr[x][k] = '0';
}
}
int num = 0,j = 0;
if(numRows == 1){
return s;
}
for(int i = 0;i<1000;i++){
if(i % (numRows-1) == 0){
for(;j < numRows;j++){
if(num >s.length()-1){
break;
}
carr[j][i] = s[num++];
}
j--;
}else{
carr[j][i] = s[num++];
}
if(num >s.length()-1){
break;
}
j--;
}
string r="";
for(int x = 0;x < numRows;x++){
for(int k = 0;k<1000;k++){
if(carr[x][k] != '0'){
r.push_back(carr[x][k]);
}
}
}
return r;
}
};
解题过程
首先用任意一种方式将二维数组遍历赋值为一个不可能出现的字符,用此判断该二维表中是否有我们存入的字母。然后通过列优先,把某一列的值固定住,通过二层循环更新行的值,实现Z字形存入二维表。有些列要存Numrows大小的数,有的列只要存一个。我们可以用判断语句,来实现,可以通过枚举找规律,当列数i % (numrows - 1) == 0时,我们就应该循环存入Numrows大小的字母,除开上面的情况之外,我们都只需要存入一个字母。我们可以发现,存入的时候无非就两种状态,要么存入一列值,要么存入一个值,第一种情况的满足条件我们实现了,第二种情况都是连续存入一个值,列数递增,行数递减,且行数一直在0-numrows和numrows-0之间变换,所以在定义行的变量时我们不应该在for里面定义导致每次都初始化,假设j为行变量,在每一次存完一列值的循环过后j的值都会比当时存入j行时的值大1,所以在每次完成循环存入,我们就要在循环结束外,判断语句内的地方做j--,此时j的值才恢复正常,可以观察到每次连续输入一个值的行变量是要递减的直到j=0(其实这里我发现判断循环开始语句可以以j==0为条件的,但是用j==0 条件会使执行用时会比i%(numrows -1)==0长),所以我们在整个大循环的最后还要进行一次j--。再设置一个判断我们取字符串里取完的临界条件就行用于退出循环。
最后当我们将字符串存完到二维表里,我们就可以按照行优先遍历二维数组,创建一个字符串,检查每个位置是否存进过字母,存进过就push_back到字母串里,直到访问完,返回这个字符串就解决了!
PS:特殊情况当Numrows=1时,我们直接返回字符串就行
复杂度
- 时间复杂度: O(n)
- 空间复杂度: O(n)