将字符串按Z字型放入二维数组中,然后遍历按行遍历二维数组,得到结果。主要计算每个字符在数组中的位置即可。
行数就是方法第二个入参,数组列数的计算:每numRows + numRows - 2个数为一组,前numRows个数一列,后 numRows - 2个数,每个数一列;
不过这样的方式除了遍历字符串以外,还要额外扫描一次二维数组,增加耗时。
按照分组的思路(每numRows + numRows - 2个数为一组,前numRows个数一列,后 numRows - 2个数,每个数一列),最后输出的结果从前往后应该是(每组的第一个元素)+(每组第二个元素+每组倒数第一个元素) + (每组第三个元素+每组倒数第二个元素)....
按例子
1.字符串为 "PAYPALISHIRING"
行数为 3
时,排列如下:
P A H N A P L S I I G Y I R
即每个元素索引排列为
0 4 8 12
1 3 5 7 9 11 13
2 6 10
可分为batch = 4组。(0,1,2,3)(4,5,6,7)....(12,13)
2.
输入:s = "PAYPALISHIRING", numRows = 4时batch = 6
0 6 12
1 5 7 11 13
2 4 8 10
3 9
我们直接遍历二维数组的每一行,可以发现每个元素的index其实都是行、列和batch等参数的公式计算而得。
public String convert(String s, int numRows) {
if (numRows == 1) {
return s;
}
int batchs = s.length() / (numRows + numRows - 2);
if (s.length() % (numRows + numRows - 2) != 0) {
batchs++;
}
char[] z = new char[s.length()];
int zIndex = 0;
int batchNum = (numRows<<1) - 2;
int index = 0;
int indexZ = 0;
for (int i = 0; i < numRows; i++) {
for (int batch = 0; batch < batchs; batch++) {
index = i + batch * batchNum;
if (index < s.length()) {
z[zIndex++] = s.charAt(index);
} else {
continue;
}
if (i > 0 && i < numRows - 1) {
// 中间行,每个batch之间都要多加一个数
indexZ = batchNum * (batch + 1) - i;
if (indexZ < s.length()) {
z[zIndex++] = s.charAt(indexZ);
} else {
continue;
}
}
}
}
return String.valueOf(z);
}
优化:
我的代码里虽然是双循环,但是基本上每次都能遍历到一个元素,所以时间复杂度比O(n)大一点,因为else跳出循环的这块逻辑有问题,存在空循环的操作,所以每行开始的时候,能计算出本行的末尾的边界index,可以将时间优化到O(n)。
1。优化了else的逻辑之后,两个for循环遍历的次数达到了最少次数即numRows*batchs次,可是时间效率还是3ms;
2。又去掉了代码中的除法,取模和乘法计算,时间还是3ms。
将循环次数控制在最小并且减少乘除计算,并没有提升效率,然后看了下力扣上,这题最快的答案很少,对比了几个2ms的答案,感觉循环次数比我还多很多,百思不得其解,对比了半天我把代码中用到字符串长度的s.length()操作都替换掉了,一开始就int n = s.length();之后不再调用s的方法,发现!!!时间2ms了。。。。。。。。。。。
看来以后做题的过程中减少方法调用是一个提升速度的方法?
贴一个各种优化后的代码,时间为2ms和3ms,大概一半一半的几率(2ms的优化情况主要还是靠替换s.length(),其他修改基本没起作用)
class Solution {
public String convert(String s, int numRows) {
int n = s.length();
if (n <= 2 || numRows == 1) {
return s;
}
int batchNum = (numRows<<1) - 2;
char[] z = new char[s.length()];
int zIndex = 0;
int index = 0;
int indexZ = 0;
int slengCopy = n;
int bb = 0;//代替batch * batchNum
for (int i = 0; i < numRows; i++) {
slengCopy = n;
bb = 0;
for (; slengCopy > 0;) {
// index = i + batch * batchNum;
index = i + bb;
if (index < n) {
z[zIndex++] = s.charAt(index);
}
if (i == numRows - 1 && (i + bb + batchNum) >= n) {
break;
}
if (i > 0 && i < numRows - 1) {
indexZ = batchNum + bb - i;
if (indexZ < n) {
z[zIndex++] = s.charAt(indexZ);
}
if ((i + bb + batchNum) >= n) {
break;
}
}
slengCopy -= batchNum;
bb += batchNum;
}
}
return String.valueOf(z);
}
}