LeetCode6---Z字形变换

将字符串 "PAYPALISHIRING" 以Z字形排列成给定的行数:

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

这个题就是一个简单的模拟题,给定一个字符串,按照给定的行数对字符串进行Z字形重排序。假设有一个二维数组,行数为给定值,
1、将字符串先按纵向填充,
2、到尾行以后再横向填充,
3、到首行再重复以上过程。
由此我们很容易就写出以下实现:

public String convert(String s, int numRows) {
        if (s.length() == 0){
            return "";
        }
        if (numRows == 1){
            return s;
        }

        char[][] zMap = new char[numRows][s.length()];

        int col = 0;
        int row = 0;
        //移动方向   true表示纵向移动  false表示横向移动
        boolean direction = true;

        int pos = 0;
        while (pos < s.length()) {
            if (direction) {
                //纵向移动
                zMap[row][col] = s.charAt(pos);
                ++row;
                if (row >= numRows) {
                    //移动到最后一行后改为横向移动 切回纵向向上回退一行
                    direction = false;
                    --row;
                }
            } else {
                //横向移动
                --row;
                ++col;
                zMap[row][col] = s.charAt(pos);
                if (row <= 0) {
                    //纵向坐标到达首行后改为纵向移动 纵向想下移动一行
                    direction = true;
                    ++row;
                }
            }
            pos++;
        }
        StringBuilder rs = new StringBuilder();
        for (int i = 0; i < numRows; ++i) {
            for (int j = 0; j <= col; ++j) {
                if (zMap[i][j] != '\0') {
                    rs.append(zMap[i][j]);
                }
            }
        }
        return rs.toString();
    }

我们生成二维数组的过程为O(n),但是最后我们需要遍历一遍二维数组,导致复杂度变成了O(n^2),因此我们可以对此过程进行优化。二维数组我们实际上只用了一部分,中间为空字符的是没用的,最后访问的时候实际上是将二维数组的几行进行了拼接,因此在开始我们就可以直接使用numRows个字符串来存储二维数组的每行,最后对字符串进行拼接即可,复杂度变为O(n)。
改写如下:

public String convert2(String s, int numRows) {
        if (s.length() == 0){
            return "";
        }
        if (numRows == 1){
            return s;
        }

        StringBuilder[] strs = new StringBuilder[numRows];
        for (int i = 0; i < strs.length; i++) {
            strs[i] = new StringBuilder();

        }

        int row = 0;
        //移动方向   true表示纵向移动  false表示横向移动
        boolean direction = true;

        int pos = 0;
        while (pos < s.length()) {
            if (direction) {
                //纵向移动
                strs[row].append(s.charAt(pos));
                ++row;
                if (row >= numRows) {
                    //移动到最后一行后改为横向移动 切回纵向向上回退一行
                    direction = false;
                    --row;
                }
            } else {
                //横向移动
                --row;
                strs[row].append(s.charAt(pos));
                if (row <= 0) {
                    //纵向坐标到达首行后改为纵向移动 纵向想下移动一行
                    direction = true;
                    ++row;
                }
            }
            pos++;
        }
        StringBuilder rs = new StringBuilder();
        for (int i = 0; i < numRows; ++i) {
            rs.append(strs[i]);
        }
        return rs.toString();
    }

猜你喜欢

转载自blog.csdn.net/qq_36666651/article/details/80552475