必刷算法100题之z字形变换

题目链接

6. Z 字形变换 - 力扣(LeetCode)

题目解析

给定一个字符串, 按照从上到下进行z排列,输出从左往右的z字行数组

算法原理

解法1

模拟这个流程

创建一个矩阵, 行数为n,列数我们就根据这个字符有多少个作为列数

然后把字符一个一个进行填进去

最后从左往右进行遍历,取出字符,然后返回结果

解法2: 找规律, 99%的模拟题都可以找规律来解决,根据模拟的结果来反推规律, 然后验证规律

我们数组里面放下标,而不是元素

我们第一行的字符就可以根据0+公差来进行查找

如何计算公差: d = 2n - 2

于是第0行和最后一行的元素,我们就可以使用公差来进行计算

中间的行的元素的计算(1-n-2)行的计算,一直到len位置

进行规律的验证

注意: n = 1的时候需要单独处理, 不然会死循环

代码编写

法1 用模拟来进行优化

s来进行拼接

class Solution {
    public String convert(String ss, int numRows) {
        int len = ss.length();
        if (numRows == 1) {
            return ss;
        }
        // 计算差值
        int d = 2 * numRows - 2;
        String s = "";
        // 拼接第一层
        for (int i = 0; i < len; i += d) {
            s += ss.charAt(i);
        }
        // 拼接中间的层
        for (int i = 1; i < numRows - 1; i++) {
            for (int j = i, k = d - j; j < len || k < len; j += d, k += d) {
                // j是表示是第i层的第一个, k表示第ic层的第二个
                if (j < len) {
                    s += ss.charAt(j);
                }
                if (k < len) {
                    s += ss.charAt(k);
                }
            }
        }
        // 拼接最后一层
        for (int i = numRows-1; i < len; i += d) {
            s += ss.charAt(i);
        }
        return s;
    }
}

StringBuilder来进行拼接

s.append(字符)->拼接

s.toString() -> 把StrungBuilder转成String

class Solution {
    public String convert(String s, int numRows) {
        // 使用StringBuilder来进行拼接
        if (numRows == 1) {
            return s;
        }
        StringBuilder ret = new StringBuilder();
        int n = s.length();
        // 计算差值
        int d = 2 * numRows - 2;
        // 计算第一行
        for (int i = 0; i < n; i += d) {
            ret.append(s.charAt(i));
        }
        // 处理中间行
        for (int k = 1; k < numRows - 1; k++) {
            for (int i = k, j = d - i; i < n || j < n; i += d, j += d) {// 俩个情况满足一个就要进行拼接
                // 分情况讨论
                if (i < n) {
                    ret.append(s.charAt(i));
                }
                if (j < n) {
                    ret.append(s.charAt(j));
                }
            }
        }
        // 处理最后一行
        for (int i = numRows - 1; i < n; i += d) {
            ret.append(s.charAt(i));
        }
        return ret.toString();
    }
}

暴力

class Solution {
    public String convert(String ss, int numRows) {
        char[] ch = ss.toCharArray();
        int n = ss.length();
        if (numRows == 1) {
            return ss;
        }
        // 创建二维数组,然后把字符串的下标放进去
        char[][] arr = new char[numRows][n];
        int row = 0;// 定义行
        int col = 0;// 定义列
        // 按照z字形状, 把字符数组的下标放进去
        int i = 0;
        while (i < n) {
            // 处理每一列
            while (i < n && row < numRows) {
                arr[row][col] = ch[i];
                i++;
                if (row < numRows) {
                    row++;
                }
            }
            row--;
            // 此时第一列已经处理完,处理拐角部分,此时row==numRows
            while (i < n && row > 0) {
                // 先把列进行转化
                col++;
                // 行逐渐递减
                row--;
                arr[row][col] = ch[i];
                i++;
            }
            row++;
        }

        // 此时得到了一个arr数组
        // 我们通过公式来遍历下标
        String rs = "";
        for (int j = 0; j < arr.length; j++) {
            for (int w = 0; w < arr[0].length; w++) {
                if (arr[j][w] != '\u0000') {
                    rs += arr[j][w];
                }
            }
        }
        return rs;
    }
}

注意,如果只是一行, 那么久直接返回这个字符串即可

猜你喜欢

转载自blog.csdn.net/2201_75880772/article/details/146453318
今日推荐