打卡活动8-算法7. Z 字形变换

189 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目

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

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

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

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

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

string convert(string s, int numRows);

示例 1:

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

示例 2:

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I

示例 3:

输入:s = "A", numRows = 1
输出:"A"

提示:

  • 1 <= s.length <= 1000
  • s 由英文字母(小写和大写)、',''.' 组成
  • 1 <= numRows <= 1000

二、我的解答

第一次解答:

class Solution {    public static String convert(String s, int numRows) {        List<Character>[] all = new List[numRows];        for (int i = 0; i < numRows; i++) {            List<Character> row = new ArrayList<>();            all[i] = row;        }        int step = numRows + numRows - 2;        for (int i1 = 0; i1 < s.length(); i1 = i1 + step) {            for (int i2 = 0; i2 < numRows; i2++) {                int index = i1 + i2;                if (index < s.length()) {                    all[i2].add(s.charAt(index));                    int nextOneRowIndex = i1 + step;                    if (i2 != 0 && i2 != numRows - 1) {                        if (nextOneRowIndex - i2 < s.length()) {                            all[i2].add(s.charAt(nextOneRowIndex - i2));                        }                    }                }            }        }        String result = "";        for (int i = 0; i < all.length; i++) {            List<Character> characters = all[i];            for (int i1 = 0; i1 < characters.size(); i1++) {                result = result + characters.get(i1);            }        }        //PAHNAPLSIIGYIR        return result;    }}

报错:超出内存限制

第二次解答:

class Solution {
  public static String convert(String s, int numRows) {
        if (s.length() == 1 || numRows == 1) {
            return s;
        }
        List<Character>[] all = new List[numRows];
        for (int i = 0; i < numRows; i++) {
            List<Character> row = new ArrayList<>();
            all[i] = row;
        }
        int step = numRows + numRows - 2;

        for (int i1 = 0; i1 < s.length(); i1 = i1 + step) {
            for (int i2 = 0; i2 < numRows; i2++) {
                int index = i1 + i2;
                if (index < s.length()) {
                    all[i2].add(s.charAt(index));
                    int nextOneRowIndex = i1 + step;
                    if (i2 != 0 && i2 != numRows - 1) {
                        if (nextOneRowIndex - i2 < s.length()) {
                            all[i2].add(s.charAt(nextOneRowIndex - i2));
                        }
                    }
                }
            }
        }
        String result = "";
        for (int i = 0; i < all.length; i++) {
            List<Character> characters = all[i];
            for (int i1 = 0; i1 < characters.size(); i1++) {
                result = result + characters.get(i1);
            }
        }
        //PAHNAPLSIIGYIR
        return result;
    }
}

三、系统解答

方法一:利用二维矩阵模拟

思路与算法

class Solution {
    public String convert(String s, int numRows) {
        int n = s.length(), r = numRows;
        if (r == 1 || r >= n) {
            return s;
        }
        int t = r * 2 - 2;
        int c = (n + t - 1) / t * (r - 1);
        char[][] mat = new char[r][c];
        for (int i = 0, x = 0, y = 0; i < n; ++i) {
            mat[x][y] = s.charAt(i);
            if (i % t < r - 1) {
                ++x; // 向下移动
            } else {
                --x;
                ++y; // 向右上移动
            }
        }
        StringBuffer ans = new StringBuffer();
        for (char[] row : mat) {
            for (char ch : row) {
                if (ch != 0) {
                    ans.append(ch);
                }
            }
        }
        return ans.toString();
    }
}

复杂度分析 时间复杂度:O(r⋅n),其中r=numRows,n 为字符串 s 的长度。时间主要消耗在矩阵的创建和遍历上,矩阵的行数为 r,列数可以视为O(n)。 

 空间复杂度:O(r⋅n)。矩阵需要O(r⋅n) 的空间。

方法二:压缩矩阵空间

思路与算法

class Solution {
    public String convert(String s, int numRows) {
        int n = s.length(), r = numRows;
        if (r == 1 || r >= n) {
            return s;
        }
        StringBuffer[] mat = new StringBuffer[r];
        for (int i = 0; i < r; ++i) {
            mat[i] = new StringBuffer();
        }
        for (int i = 0, x = 0, t = r * 2 - 2; i < n; ++i) {
            mat[x].append(s.charAt(i));
            if (i % t < r - 1) {
                ++x;
            } else {
                --x;
            }
        }
        StringBuffer ans = new StringBuffer();
        for (StringBuffer row : mat) {
            ans.append(row);
        }
        return ans.toString();
    }
}

复杂度分析

  • 时间复杂度:O(n)。

  • 空间复杂度:O(n)。压缩后的矩阵需要O(n) 的空间。