Z字形变换

Z 字形变换

题目:

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

*P   A   H   N*
*A P L S I I G*
*Y   I   R*

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I
  • 1 <= s.length <= 1000
  • s 由英文字母(小写和大写)、',''.' 组成
  • 1 <= numRows <= 1000

自行解答:

string convert(string s, int numRows) {
    if(numRows == 1){
        return s;
    }
    //每一份对应多少列
    int partColum = numRows-1;
    //每一份含有的字符的长度
    int partLength = 2 *numRows-2;
    //总共多少份
    int partNum = s.length() / partLength;
    //所有的列数
    int columNum = 0;
    //整份剩下的字符长度
    int partReset = s.length() % partLength;

    if(partReset == 0){
        columNum =  partNum *partColum;
    } else if(partReset <=numRows){
        columNum =  partNum *partColum +1;
    } else {
        columNum = partNum *partColum + partReset - numRows+1;
    }
    vector< vector<string> > arrResult;
    for(int i = 0;i<numRows;i++){
        vector<string> v1;
        v1.resize(columNum);
        arrResult.push_back(v1);
    }
    int m =0;
    int n = 0;
    int numCount = 0;
    for(int i = 0;i<=partNum;i++){
        if(i!= partNum){
            numCount = partLength;
        } else{
            numCount =  partReset;
        }
        for(int count = 0;count <numCount;count++){
            arrResult[m][n] = s[i*partLength +count];
            if(count < numRows-1){
                m++;
            } else{
                m--;
                n++;
            }

        }
    }
    string result = "";
    for(int i = 0;i<numRows;i++){
        for(int j = 0;j<columNum;j++){
            if(arrResult[i][j].size() != 0){
                result += arrResult[i][j];
            }
        }
    }
    return result;
}

思路分析:

思路比较简单,按照字符串走向将字符按个记录在二维数组中,最后按行遍历取出来数组即可,具体需要借助的变量参数 即含义见上面的代码注释,但是此算法时间和空间复杂度较高,可进一步推出另外一种算法

空间复杂度:使用了二维数组存储变量,也就是arrResult大小的变量,所以空间复杂度应该为:O(numrows *columNum ) 即O(N2),占用了额外的空间

时间复杂度: 因为只遍历原数组一次,也就是O(N)

官方解答

官方 提供了2种解答,方案2是按照排列而成的字符进行位置规律进行数学计算,是自行解答的思路的进一步体现,再此不赘述,可参考官方解法2_按行访问,提供下官方的解法一,代码实现如下:

class Solution {
public:
    string convert(string s, int numRows) {

        if (numRows == 1) return s;

        vector<string> rows(min(numRows, int(s.size())));
        int curRow = 0;
        bool goingDown = false;

        for (char c : s) {
            rows[curRow] += c;
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }

        string ret;
        for (string row : rows) ret += row;
        return ret;
    }
};

思路分析:

1:遍历字符串s ,准备结果动态数组 rows,准备2个变量,

  • curRow:遍历字符s的时候,当前字符按照题目要求应该所处的行的位置
  • goingDown:每次遍历时,遍历的顺序是向上还是向下,根据循环的位置会进行更新

2:遍历字符s

  • 将字符s的当前位置的字符c 加到对应的row对应的行中
  • 更新goingDown当前结果
  • 根据goingDown确认当前行 curRow的结果

3:整合结果字符,将rows按照行输出,即最终结果

复杂度分析:

时间复杂度:只遍历1次字符串,因此复杂度为 O(n)

空间复杂度:有限的变量 + 存储Z字形的数组(长度为s的长度),复杂度O(N)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容