ZigZag转换 算法

题目出处

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的格式。


分析


一种直观的解法就是根据上面描述的思路来处理, 后面会符上解决代码:

  1. 设定一个m行的字符串数组。
  2. 遍历字符串,把字符放到指字的字符串中去。
  3. 逐行把字符串相加得到结果

分析这方法复杂度分析:

  • 时间复杂度为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;
    }






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章