題目出處
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;
}