【LeetCode】No.6. Zigzag Conversion -- Java Version

78 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 题目链接: leetcode.com/problems/zi…

1. 题目介绍(之字形)

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

【Translate】: 字符串“PAYPALISHIRING”在给定的行数上以之字形的方式书写,如下所示:(为了更好的可读性,您可能需要使用固定的字体来显示此模式) sample

And then read line by line: "PAHNAPLSIIGYIR"

【Translate】: 按行读取 "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

【Translate】: 编写代码,该代码将接受一个字符串,并根据给定的行数进行转换 convert

测试用例:

test1 test2 test3

约束:

Constraints

2. 题解

2.1 从上到下 按列存储( StringBuffer[] )

  该题解来源于dylan_yu。其基本思想就是通过生成对应长度的StringBuffer[]去根据限定条件存储对应的字符。通过i++一直遍历到字符串结束,同时又通过nRows限制了每一列该存储的数据。vertically down负责筛选正常列中的数据,obliquely up负责筛选Z型中间的数据。 在这里插入图片描述

class Solution {
    public String convert(String s, int nRows) {
        char[] c = s.toCharArray();
        int len = c.length;
        
        // 创建StringBuffer[]
        StringBuffer[] sb = new StringBuffer[nRows];
        System.out.println(sb.length);
        // 对StringBuffer[]初始化
        for (int i = 0; i < sb.length; i++) sb[i] = new StringBuffer();

        int i = 0;
        while (i < len) {
            for (int idx = 0; idx < nRows && i < len; idx++) // vertically down
                sb[idx].append(c[i++]);
            for (int idx = nRows-2; idx >= 1 && i < len; idx--) // obliquely up
                sb[idx].append(c[i++]);
        }
        for (int idx = 1; idx < sb.length; idx++)
            sb[0].append(sb[idx]);
        return sb[0].toString();
    }
}

case1

2.2 从上到下 按列存储( StringBuilder[] )

  与2.1中的思想一致,只不过将 StringBuffer[] 替换成了 StringBuilder[],两者功能相同,但是StringBuilder[]的速度要比StringBuffer[]快,但是安全性要低。

    public String convert(String s, int numRows) {
       if (numRows <=1 || s.length() <= numRows) return s;
       // make numRows of StringBuilder array and initialize
        StringBuilder[] sb = new StringBuilder[numRows];
        for (int i = 0; i < sb.length; i++) sb[i] = new StringBuilder();
        int curRow = 0;
        boolean godown = false;
        char[] charArray = s.toCharArray();
        for (char c: charArray) {
            sb[curRow].append(c);
            // determine next move, go down or up 
            if (curRow == 0 || curRow == numRows - 1)  godown = !godown;   
            curRow += godown? 1: -1;
        }
        StringBuilder ret = new StringBuilder();
        for (StringBuilder data: sb) ret.append(data);
        return ret.toString();
    }

在这里插入图片描述

2.3 Sort by Row -- O(n)

  Solution中的Approach 1。从左到右遍历s,将每个字符附加到适当的行。可以使用两个变量跟踪适当的行:当前行和当前方向。只有当我们向上移动到最上面一行或向下移动到最下面一行时,当前的方向才会改变。

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();
    }
}

case3

2.4 Visit by Row -- O(n)

  Solution中的Approach 2。首先访问第0行中的所有字符,然后是第1行,然后是第2行,依此类推……;纯数学推理了。 在这里插入图片描述

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

        if (numRows == 1) return s;

        StringBuilder ret = new StringBuilder();
        int n = s.length();
        int cycleLen = 2 * numRows - 2;

        for (int i = 0; i < numRows; i++) {
            for (int j = 0; j + i < n; j += cycleLen) {
                ret.append(s.charAt(j + i));
                if (i != 0 && i != numRows - 1 && j + cycleLen - i < n)
                    ret.append(s.charAt(j + cycleLen - i));
            }
        }
        return ret.toString();
    }
}

在这里插入图片描述

3. 可参考

[1] Java StringBuffer 和 StringBuilder 类

[2] [LeetCode]006. 之字折线转换