问题描述:输入一个字符串和给定数字nums,将字符串用长为nums的Z字形型展开,输出转换后的字符序列。
例:“PAHPZAISH”, 3
P____P____S
A _H_Z__I__H
H____A
输出:PPSAHZIHHA思路:
- Z字入桶
把构建的Z字形按行看,每行对应一个桶,只要以Z字形将字符串按序投入桶内即可。
时间复杂度:o(n)
空间复杂度:o(n)
- 按行输出
容易知道第0行和第nums-1行的下标数为行数与2nums - 2的累和,对于中间行数来说,简单对一个N的基本情况进行分析,观察每行第二个元素,可以看出行数每下一次,每行第一二个元素间隔会递减2个,即(2nums-2)- 2i,再观察第三个元素,可以看到第二三个元素间每下一行间隔加2,即2i;由于后面情况与此相同,故中间行数元素间间隔为前两者的交替。由此设计算法按下标遍历。
0_____6
1___5_7
2_4___8
3_____9
时间复杂度:o(n)
空间复杂度:o(n)
//java
//Z字入桶
class Solution {
public String convert(String s, int numRows) {
if(numRows < 2) return s;//长度太小直接输出即可
ArrayList<StringBuilder> rows = new ArrayList<StringBuilder>();//构建字符串列表(放桶区域)
for(int i = 0; i < numRows; ++i) rows.add(new StringBuilder());//加入numRows个桶
int i = 0, flag = -1;//i表示第几个桶,flag为掉头参数
for(char str: s.toCharArray()){
rows.get(i).append(str);
if(i == 0 || i == numRows - 1) //该掉头了
flag = -flag;
i += flag;
}
StringBuilder res = new StringBuilder();//创建一个字符串准备收集桶中元素
for(StringBuilder row: rows) res.append(row);
return res.toString();
}
}
//按行遍历
class Solution {
public String convert(String s, int numRows) {
if(numRows < 2) return s;
int len = s.length();
int step = 2 * numRows - 2;//一般间隔
StringBuilder res = new StringBuilder();//最终字符串
for(int i = 0; i < numRows; ++i){
int add = 2 * i;//中间行数步长调整
int j = i;
while(j < len){//遍历下标小于字符串长度
res.append(s.charAt(j));
add= step - add;//通过add值调整间隔(奇数次为step-add,偶数次为add)
j += (i == 0 || i == numRows - 1)? step : add;//行数区分
}
}
return res.toString();
}
}