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 <= 1000s由英文字母(小写和大写)、','和'.'组成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) 的空间。