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;
    }






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