原题链接:https://leetcode-cn.com/problems/zigzag-conversion/description/
题目描述:
知识点:字符串
思路一:用一个二维char型数组来存储各字符,再从数组中按一定顺序取出字符拼接出结果
这个思路模拟的就是我们手工排列字符得出结果的一个过程。我们把排列出的Z字形图按列存储,每一列都是一个长度为numRows的数组。最后我们取出结果时,先取出每一列中的第一个元素,再取出每一列中的第二个元素,依次类推,直至取完所有的元素。
这个思路的时间复杂度是O(m * numRows),其中m为排列出的Z字形的列数,由于该列数与字符串的长度成正比,我们也可以把时间复杂度写成O(n * numRows),其中n为字符串s的长度。对于空间复杂度,我们需要一个二维数组来存储字符串s中所有的字符,和时间复杂度一样,是O(m * numRows)级别的,同理我们可以写成是O(n * numRows)级别的。
JAVA代码:
public class Solution {
public String convert(String s, int numRows) {
int n = s.length();
if(n <= numRows || numRows == 1 || numRows == 0) {
return s;
}
int quotient = (n - numRows) / (2 * (numRows - 2) + 2);
int mod = (n - numRows) % (2 * (numRows - 2) + 2);
int cols = 1;
if(mod <= numRows - 2) {
cols += quotient * (numRows - 1) + mod;
}else {
cols += (quotient + 1) * (numRows - 1);
}
char[][] array = new char[cols][numRows];
int k = 0;
for (int i = 0; i < cols; i++) {
if(k < n) {
if(i % (numRows - 1) == 0) {
for (int j = 0; j < numRows; j++) {
array[i][j] = s.charAt(k++);
if(k >= n) {
break;
}
}
}else {
array[i][numRows - i % (numRows - 1) - 1] = s.charAt(k++);
}
}
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < cols; j++) {
if(array[j][i] != 0) {
stringBuilder.append(array[j][i]);
}
}
}
return stringBuilder.toString();
}
}
LeetCode解题报告:
思路二:按顺序遍历字符串s,模拟ZigZag的全过程
在思路一中,我们保存了每一个字符之外还保存了大量的0,而这些0的位置其实是没必要保存的。因此我们对于每一行都设立一个StringBuilder型的变量来保存结果,自动忽略了0的位置。
设立一个int型变量zigZag来模拟我们指针的走向,当row为0时我们设置zigZag为1,当row为numsRow - 1时我们设置zigZag为-1。其实看代码很好理解这个过程。
我们只遍历了一遍字符串s,显然时间复杂度是O(n)级别的,其中n为字符串s的长度。而对于空间复杂度,我们没有保存任何额外的0,我们的空间复杂度也是O(n)级别的。
JAVA代码:
public class Solution {
public String convert(String s, int numRows) {
int n = s.length();
if(n <= numRows || numRows == 1 || numRows == 0) {
return s;
}
StringBuilder[] stringBuilders = new StringBuilder[numRows];
for (int i = 0; i < numRows; i++) {
stringBuilders[i] = new StringBuilder();
}
int row = 0;
int zigZag = 1;
for (int i = 0; i < n; i++) {
stringBuilders[row].append(s.charAt(i));
row += zigZag;
if(row == numRows - 1) {
zigZag = -1;
}
if(row == 0) {
zigZag = 1;
}
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < stringBuilders.length; i++) {
result.append(stringBuilders[i]);
}
return result.toString();
}
}
LeetCode解题报告:
思路三:寻找数学规律
用小数据进行测试,很容易得到本题每一行字符在原字符串s中的索引的规律,比如第一行字符和最后一行字符的索引间隔是2 * numRows - 2,其余各行的规律也可以依次得出,只要我们在草稿纸上仔细推导一遍即可,这里我就不详细证明了。
此思路的时间复杂度是O(numRows * n),其中n为字符串s的长度。而空间复杂度,由于这个方法也没有存储多余的0字符,故空间复杂度是O(n)级别的。
JAVA代码:
public class Solution {
public String convert(String s, int numRows) {
int n = s.length();
if(n <= numRows || numRows == 1 || numRows == 0) {
return s;
}
StringBuilder[] stringBuilders = new StringBuilder[numRows];
for (int i = 0; i < numRows; i++) {
stringBuilders[i] = new StringBuilder();
}
int interval = 2 * numRows - 2;
int row = 0;
//处理第一行
for (int i = 0; i < n; i += interval) {
stringBuilders[row].append(s.charAt(i));
}
//处理剩下的所有行
for (row = 1; row < numRows; row++) {
for (int i = row; i < n; i++) {
if(row != numRows - 1) {
if((i - row + 2 * row) % interval == 0) {
stringBuilders[row].append(s.charAt(i));
}
if((i - row) % interval == 0) {
stringBuilders[row].append(s.charAt(i));
}
}else {
if((i - row) % interval == 0) {
stringBuilders[row].append(s.charAt(i));
}
}
}
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < stringBuilders.length; i++) {
result.append(stringBuilders[i]);
}
return result.toString();
}
}
LeetCode解题报告: