【43.Z字型变换】

63 阅读1分钟

题目

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

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

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

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

示例 1:

输入: s = "PAYPALISHIRING", numRows = 3
输出: "PAHNAPLSIIGYIR"

题解

方式一:模拟

思路最简单

public String convert(String s, int numRows) {
    // 不需要处理
    int len = s.length();
    if (len <= numRows || numRows == 1) {
        return s;
    }
    
    // 模拟,把字符放到数组里面;这里数组长度应该还能小一点,懒得算了
    // 想优化可以把二位数组换成StringBuilder数组
    char[][] simulation = new char[numRows][len];
    int m = 0; 
    int n = 0;
    char[] chars = s.toCharArray();
    int count = 0;
    int index = 0;
    while (count < len) {
        // down
        while (m < numRows && count < len) {
            simulation[m++][n] = chars[index++];
            count++;
        }
        m -= 2;
        n++;
        // up
        while (m >= 0 && count < len) {
            simulation[m--][n++] = chars[index++];
            count++;
        }
        m += 2;
        n--;
    }

    // 遍历数组取结果
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < simulation.length; i++) {
        for (int j = 0; j < simulation[0].length; j++) {
            if (simulation[i][j] != 0) {
                sb.append(simulation[i][j]);
            }
        }
    }

    return sb.toString();
}

方式二:利用flag转向(大神思路)

public String convert(String s, int numRows) {
    int n = s.length();
    if (n <= numRows || numRows == 1) {
        return s;
    }
    
    List<StringBuilder> list = new ArrayList<>();
    for (int i = 0; i < numRows; i++) {
        list.add(new StringBuilder());
    }
    
    int flag = -1;
    int i = 0;
    for (char c: s.toCharArray()) {
        list.get(i).append(c);
        // 到边界转向
        if (i == 0 || i == numRows - 1) {
            flag = -flag;
        }
        i += flag;
    }
    
    StringBuilder ans = new StringBuilder();
    for (StringBuilder sb: list) {
        ans.append(sb);
    }
    
    return ans.toString();
}

总结

算法:模拟