题目链接
题目解析
给定一个字符串, 按照从上到下进行z排列,输出从左往右的z字行数组
算法原理
解法1
模拟这个流程
创建一个矩阵, 行数为n,列数我们就根据这个字符有多少个作为列数
然后把字符一个一个进行填进去
最后从左往右进行遍历,取出字符,然后返回结果
解法2: 找规律, 99%的模拟题都可以找规律来解决,根据模拟的结果来反推规律, 然后验证规律
我们数组里面放下标,而不是元素
我们第一行的字符就可以根据0+公差来进行查找
如何计算公差: d = 2n - 2
于是第0行和最后一行的元素,我们就可以使用公差来进行计算
中间的行的元素的计算(1-n-2)行的计算,一直到len位置
进行规律的验证
注意: n = 1的时候需要单独处理, 不然会死循环
代码编写
法1 用模拟来进行优化
s来进行拼接
class Solution {
public String convert(String ss, int numRows) {
int len = ss.length();
if (numRows == 1) {
return ss;
}
// 计算差值
int d = 2 * numRows - 2;
String s = "";
// 拼接第一层
for (int i = 0; i < len; i += d) {
s += ss.charAt(i);
}
// 拼接中间的层
for (int i = 1; i < numRows - 1; i++) {
for (int j = i, k = d - j; j < len || k < len; j += d, k += d) {
// j是表示是第i层的第一个, k表示第ic层的第二个
if (j < len) {
s += ss.charAt(j);
}
if (k < len) {
s += ss.charAt(k);
}
}
}
// 拼接最后一层
for (int i = numRows-1; i < len; i += d) {
s += ss.charAt(i);
}
return s;
}
}
StringBuilder来进行拼接
s.append(字符)->拼接
s.toString() -> 把StrungBuilder转成String
class Solution {
public String convert(String s, int numRows) {
// 使用StringBuilder来进行拼接
if (numRows == 1) {
return s;
}
StringBuilder ret = new StringBuilder();
int n = s.length();
// 计算差值
int d = 2 * numRows - 2;
// 计算第一行
for (int i = 0; i < n; i += d) {
ret.append(s.charAt(i));
}
// 处理中间行
for (int k = 1; k < numRows - 1; k++) {
for (int i = k, j = d - i; i < n || j < n; i += d, j += d) {// 俩个情况满足一个就要进行拼接
// 分情况讨论
if (i < n) {
ret.append(s.charAt(i));
}
if (j < n) {
ret.append(s.charAt(j));
}
}
}
// 处理最后一行
for (int i = numRows - 1; i < n; i += d) {
ret.append(s.charAt(i));
}
return ret.toString();
}
}
暴力
class Solution {
public String convert(String ss, int numRows) {
char[] ch = ss.toCharArray();
int n = ss.length();
if (numRows == 1) {
return ss;
}
// 创建二维数组,然后把字符串的下标放进去
char[][] arr = new char[numRows][n];
int row = 0;// 定义行
int col = 0;// 定义列
// 按照z字形状, 把字符数组的下标放进去
int i = 0;
while (i < n) {
// 处理每一列
while (i < n && row < numRows) {
arr[row][col] = ch[i];
i++;
if (row < numRows) {
row++;
}
}
row--;
// 此时第一列已经处理完,处理拐角部分,此时row==numRows
while (i < n && row > 0) {
// 先把列进行转化
col++;
// 行逐渐递减
row--;
arr[row][col] = ch[i];
i++;
}
row++;
}
// 此时得到了一个arr数组
// 我们通过公式来遍历下标
String rs = "";
for (int j = 0; j < arr.length; j++) {
for (int w = 0; w < arr[0].length; w++) {
if (arr[j][w] != '\u0000') {
rs += arr[j][w];
}
}
}
return rs;
}
}
注意,如果只是一行, 那么久直接返回这个字符串即可