一、题目描述

二、解题思路

  • 首先,定义一个矩阵,这个矩阵保存每个像素
  • 需要知道矩阵的行列,行就是传入的参数了,没什么可说的,关键是怎么求出列的数值
    • numRows = 3为例,观察发现,当列的值为0、2、4、6…时,该列就全满
    • numRows = 5为例,观察发现,当列的值为0、4、8、12…时,该列就全满
    • 设当前列值为column,可以看出规律为当column % (numRows - 1) == 0时,该列全满
    • 移动当前字符的下标i
      • 如果当前列是满列,则i在本次操作中应该移动一列的长度
        • 这里要注意,每次循环还有i++的过程,为了保证每次操作正好移动一列的长度,i加的是numRows - 1而不是numRows
        • 只有这样,才能利用每次循环额外的i++保证移动长度准确
      • 不是满列直接i++即可
  • 确定行列大小后,定义数组并初始化为'\0'
  • 像素“上色”
    • 如果此列应为满列,那么用循环将该列填满
    • 不为满列,就应该确定在该列中的那个唯一的像素点在哪一行,该行为(numRows - 1) - (col % (numRows - 1))
      • (numRows - 1):是每行最后一个元素的下标
      • 观察发现,应该上色的像素所在行的下标要比最后一行的下标上偏一个位移,这个位移的大小,就是该列相对于前一个满列偏移的大小(col % (numRows - 1))

三、解题代码

class Solution {
   
public:
    string convert(string s, int numRows) {
   
        string sln;
        auto len = s.size();
        if(!len)   return sln;
        if(len == 1 || numRows <= 1)    return s;
        int column = 0;
        for(int i = 0; i < len; i++){
   
            if(column % (numRows - 1) == 0)
                i += (numRows - 1);	//一定要减1,后面再来一个i++,每次循环正好是加上numRows
            column++;
        }

        size_t cur = 0;
        char Arr[numRows][column];

        for(int row = 0; row < numRows; row++)
            for(int col = 0; col < column; col++)
                Arr[row][col] = '\0';

        for(int col = 0; col < column && cur < len; col++)
            if(col % (numRows - 1) == 0)
                for(int row = 0; row < numRows && cur < len; row++)
                    Arr[row][col] = s[cur++];
            else
                Arr[(numRows - 1) - (col % (numRows - 1))][col] = s[cur++];
                
		cur = 0;
        for(int row = 0; row < numRows && cur < len; row++)
            for(int col = 0; col < column; col++)
                if(Arr[row][col])
                    sln += Arr[row][col];
        return sln;
    }
};

四、运行结果

注意几个测试点

  • 传入的串为空:返回空串
  • 传入的串长度为1:返回原串
  • 传入的numRows小于0:返回原串
  • 传入的numRows等于1:返回原串
  • 传入的numRows大于串长度:写第一列像素的时候不要对串越界访问