LeetCode 6. ZigZag Conversion题解

文章目录

  • 题目
    • 6. ZigZag Conversion
  • 分析
    • 思路一:移动方向
    • 思路二:静态分组
  • 题解
    • Java实现思路一
    • C++实现思路一
    • Java实现思路二

题目

6. ZigZag Conversion

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)

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

And then read line by line: “PAHNAPLSIIGYIR”

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

string convert(string s, int numRows);

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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);

分析

依据题意,此题最关键的显然就是找出所有字符所在的行数,这样才能以行的顺序将新的字符串返回。
为了找出字母与行之间的关系,我们需要发掘一些规律:

思路一:移动方向

动态考虑Z型字符串在竖直方向上的产生过程,比如:
LeetCode 6. ZigZag Conversion题解_第1张图片
就是先从P开始,以↓表示向下走,以↑表示向上走,即为P↓A↓Y↑P↑A↓L↓I……
不难发现箭头的朝向是有规律的:
只有在字符到达第一行(curRow==1)或最后一行(curRow==numRows)时,方向才会发生切换。

思路二:静态分组

我们不考虑Z字型字符串的产生过程,直接考虑其最终结果,将之分组。
LeetCode 6. ZigZag Conversion题解_第2张图片
也就是每次当字符重新回到第一行时,会产生新的一组。
这样分组以后,我们只需要知道每个字母在它所在的那组中的位置,就可以得到它的行数了。因为每组的结构都是完全一样的(都是两列,且左列numRows行,右列numRows - 2行)。
而除了最后一组以外,每组的个数是groupNum = (2 * numRows - 2)(numRows > 1时才成立)。
在分组以后,对于每组,我们不难发现:(假设当前行为 i,行从0开始数)
i == 0i == numRows-1时(也就是第一行和最后一行),该组内都只有一个字符满足。
i为其他值时,该组内总有两个字符满足。这两个字符在组中的位置分别是 i 和 groupNum - i。
综上所述,我们只需先将原先的字符串 s 进行分组,然后对于组进行遍历,就可以得到每行的字符串了。


题解

Java实现思路一

import java.util.ArrayList;
import java.util.List;

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1) return s;
        List 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();
    }
}

C++实现思路一

class Solution {
    public:

    string convert(string s, int numRows) {
        if (numRows == 1) return s;
        vector rows (min(numRows, int(s.size())));
        int curRow = 0;
        bool goingDown = false;
        for (char c : s) {
            rows[curRow] += c;
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }
        string ret;
        for (string row : rows) ret += row;
        return ret;
    }
};

以上两个都是LeetCode的官方题解。

Java实现思路二

import java.util.ArrayList;
import java.util.List;

public class Solution {

    public String convert(String s, int numRows) {
        StringBuilder returnString = new StringBuilder();
        if(numRows == 1)return s;
        int groupNum = numRows * 2 - 2;//一组的个数
        List groups = new ArrayList<>();
        for(int i=0;i

你可能感兴趣的:(LeetCode)