leetcode-Z 字形变换

344 阅读2分钟

这是我参与更文挑战的第6天,活动详情查看: 更文挑战

第6天,继续挑战第6题。这题一下子没想到什么好办法,先用暴力写法写出来。

题目

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
示例1.png 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。

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

示例 2:
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:

示例2.png

思路

一下子没想到什么好办法,还是先暴力求解吧。看了2个例子后,能明白题意就是一个字符串,先向下写,再向右上方写,循环往复,起始也不是Z字形,有点像倒Z。

倒Z.png

以示例1为例来说,可以先对字母先分组一下:下图中红色框起来的是1个大组,蓝色框起来的是1个小组。每个大组包含了2个小组,2个小组不是对称的,要区分奇数小组和偶数小组。

分组.png

可以使用一个二维数组来存储这个Z字形的形状,这个二维数组的行数就是numRows,列数可以根据大组的个数算出来,每个大组占用numRows-1列。然后遍历原始数组,根据下标判断是在哪个大组哪个小组,进而确认在二维数据中的位置,都遍历完成后,重新从上到下遍、从左到右历这个二维数组就能得到新的字符串

Java版本代码

class Solution {
    public String convert(String s, int numRows) {
        int length = s.length();
        if (length == 1 || numRows == 1) {
            return s;
        }
        // 每小组的元素个数
        int groupNum = numRows - 1;
        // 每个大组包含2个小组
        int bigGroupNum = groupNum * 2;
        // 每大组占据itemNum列,计算出最大需要的列数
        int items = length / bigGroupNum;
        // 不能整除时,最多会多出1组
        if (length % bigGroupNum> 0) {
            items = items + 1;
        }
        // 这里的itemNum是每大组占据groupNum列,items含义是总共有多少个大组
        int maxColumn = groupNum * items;
        Character[][] characters = new Character[numRows][maxColumn];
        for (int i = 0; i < length; i++) {
            char c = s.charAt(i);
            // 计算出当前字符在第几小组和第几大组,从0开始
            int groupIndex = i / groupNum;
            int bigGroupIndex = i / bigGroupNum;
            // 计算出当前字符在小组内是第几个字符
            int itemIndex = i % groupNum;
            if (groupIndex % 2 == 0) {
                // 偶数小组,向正下方
                characters[itemIndex][groupNum*bigGroupIndex] = c;
            } else {
                // 奇数小组,向右上方
                characters[numRows - 1 - itemIndex][groupNum*bigGroupIndex + itemIndex] = c;
            }
        }
        char[] chars = new char[length];
        int index = 0;
        for (int i = 0; i < numRows; i++) {
            for (int j = 0; j < maxColumn; j++) {
                if (characters[i][j] != null) {
                    chars[index++] = characters[i][j];
                }
                if (index == length) {
                    break;
                }
            }
        }
        return new String(chars);
    }
}