题目出处
https://leetcode.com/problems/zigzag-conversion/
ZigZag转换
假设 给定一个字符串“abcdefghijk…xyz”及一个转换的行数5. 对数据进行处理。
行数 | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | a | j | r | z | ||||||||||
2 | b | i | k | q | s | y | ||||||||
3 | c | h | l | p | t | x | ||||||||
4 | d | f | m | o | u | w | ||||||||
5 | e | n | v |
然后把各行的数据加起来就是:“ajrzbikqsychlptxdfmouwenv”, 就可以叫做ZigZag字符串。
ZigZag转换就是把一个字符串转换为N行的ZigZag的格式。
分析
一种直观的解法就是根据上面描述的思路来处理, 后面会符上解决代码:
- 设定一个m行的字符串数组。
- 遍历字符串,把字符放到指字的字符串中去。
- 逐行把字符串相加得到结果
分析这方法复杂度分析:
- 时间复杂度为O(n+m), (注, n为字符串长度, m为要转换的行数), 字符串相加操作耗时较长
- 开始创建了字符串数组,空间复杂度为O(m)。
所以上面算法存在两个问题:进行字符串相加操作和创建数组,来增加了空间复杂度。我们要想新的办法来解决这问题
对上面的图作过引分析
行数 | ||||||||||||||
1 | 0 | 8 | 16 | 24 | ||||||||||
2 | 1 | 7 | 9 | 15 | 17 | 23 | 25 | |||||||
3 | 2 | 6 | 10 | 14 | 18 | 22 | ||||||||
4 | 3 | 5 | 11 | 13 | 19 | 21 | ||||||||
5 | 4 | 12 | 20 |
我们注意到每一行的数字的索引是有规律的!
第一行和最后一行中索引相差是8, 即(5-1)*2
第二行时: 1+6 = 7, 7 + 2 = 9; 9 + 6 = 15; 15 + 2 = 17. … 即在 6和2交替进行,逐个确定下一个索引的位置。 注意到 6+2 = 8, 2 = 2*1(索引值)
第三行时:2+4 = 6; 6 + 4 = 10; 10+4 = 14 … 都是4, 可以理解为 是 4 和4 交替。 注意到 4+4 = 8; 4 = 2*2(索引值)
第四行时: 3+2 = 5; 5+6=10… 在6 和2之间交替。注意到 6+2 = 8; 4 = 2*3(索引值)
这规律可进行推广到第一行和最后一行。
所以根据当前位置,可以得到下一个字符的位置信息。可直接获取。
这算法的时间复杂度为O(n), 空间复杂度为 O(1)
算法代码
算法1: 传统解决方案
string convert(string s, int numRows) {
if(numRows <= 1) return s;
string tmpStr[numRows];
int cur = 0;
int direct = 1;
for(int i = 0; i < s.length(); i++){
tmpStr[cur] += s[i];
//根据拐点调转方向
if(cur == 0){
direct = 1;//
}
else if(cur == numRows-1){
direct = -1;
}
cur += direct;
}
string ret = "";
for(int i = 0; i < numRows; i++){
ret += tmpStr[i];
}
return ret;
}
算法2: 按位置填空法
string convert_0(string s, int numRows) {
if(numRows <= 1) return s;
string tmpStr(s.length(), '\0');
int cur = 0;
for(int n = 0; n < numRows; n++){
//准备移动的步数
int move[2] = {(numRows-1)*2 - 2*n, 2*n};
//根据第一行和最后一行数据进行调整
if(n == 0) move[1] = (numRows-1)*2;
if(n == numRows-1) move[0] = 2*n;
int i = n; //位置过引
int cnt = 0;
while(i < s.length()){
tmpStr[cur++] = s[i];
i+= move[(cnt++) % 2];
}
}
return tmpStr;
}