leetcode-6-Z字变换

算法

Posted by berlinfog on April 7, 2019

题目

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

比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:

L   C   I   R
E T O E S I I G
E   D   H   N

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

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例 1:

输入: s = “LEETCODEISHIRING”, numRows = 3 输出: “LCIRETOESIIGEDHN” 示例 2:

输入: s = “LEETCODEISHIRING”, numRows = 4 输出: “LDREOEIIECIHNTSG”

解释:

L D R E O E I I E C I H N T S G

答案

方法一:按行排序

思路

通过从左向右迭代字符串,我们可以轻松地确定字符位于 Z 字形图案中的哪一行。

算法

我们可以使用 min(numRows,len(s))个列表来表示 Z 字形图案中的非空行。从左到右迭代 ss,将每个字符添加到合适的行。可以使用当前行和当前方向这两个变量对合适的行进行跟踪。只有当我们向上移动到最上面的行或向下移动到最下面的行时,当前方向才会发生改变。

class Solution {
    public String convert(String s, int numRows) {

        if (numRows == 1) return s;

        List<StringBuilder> rows = new ArrayList<>();
        for (int i = 0; i < Math.min(numRows, s.length()); i++)
            rows.add(new StringBuilder());

        int curRow = 0;
        boolean goingDown = false;

        for (char c : s.toCharArray()) {
            rows.get(curRow).append(c);
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }

        StringBuilder ret = new StringBuilder();
        for (StringBuilder row : rows) ret.append(row);
        return ret.toString();
    }
}

方法二:

解决思路:按行排序,对字符串遍历,每行一次插入相应的字符。 这里相对于官方题解优化了插入方式。通过构造一个与字符串长度相等的数组 chars 用于存储转换后的字符顺序。构建一个长度为numRows的数组存储每一行下一次的插入下标。计算初始下标之后。依次插入字符即可。提交的执行时间最快约为25ms(该问题的运行速度不是很稳定,差别较大,但相对于官方demo执行速度总体上快了不少

class Solution {
    public String convert(String s, int numRows) {

        if(numRows == 1) return s;
        int[] rowIdx = new int[numRows];
        char[] chars = new char[s.length()];
        int n = 0;
        int burketSize = numRows * 2 - 2;
        int burketNum = chars.length / burketSize; 
        int rem = chars.length % burketSize;
        for(int i = 1; i < numRows; i ++){
        	int flag = i == 1 ? 1 : 2;
        	n = flag * burketNum + (rem >= i ? ( 1 + (burketSize - rem + 1 < i ? 1 : 0)) : 0);
        	rowIdx[i] = rowIdx[i-1] + n;
        }
        int flag = -1;
        int curRow = 0;
        for(char c : s.toCharArray()){
        	chars[rowIdx[curRow]] = c;
        	rowIdx[curRow] = rowIdx[curRow] + 1;
        	 if (curRow == 0 || curRow == numRows - 1) flag = -flag;
             curRow += flag;
        }
        return new String(chars);
    }
}