題目概要
將字符串按照ZigZag的順序重新排列,求排列之后的新字符串。
題目鏈接
題目解析
數(shù)學(xué)規(guī)律
尋找原先的字符在經(jīng)過ZigZag變換后的位置,直接計(jì)算出最后的字符串:
0 4 8 12
1 3 5 7 9 11 13
2 6 10 14
上例中的數(shù)字代表的是對(duì)應(yīng)的字符索引,設(shè)n為輸入的參數(shù)numRows
的值,則該例中為3,容易知道
第一行的字符索引序列為
索引序列
先考慮最后一行,容易發(fā)現(xiàn)該行的索引序列與第一行的對(duì)應(yīng)差值為n-1
中間幾行與前述兩者差距較大,我們?cè)倏匆粋€(gè)簡(jiǎn)單的實(shí)例:
0 6 12 18 24
1 5 7 11 13 17 19 23 25
2 4 8 10 14 16 20 22 26
3 9 15 21 27
看似毫無規(guī)律,但當(dāng)我們將其分為兩列分別觀察時(shí):
下標(biāo) - 1
下標(biāo) - 2
或者
下標(biāo) - 3
下標(biāo) - 4
上述兩條,也容易通過判斷是否為第奇數(shù)個(gè)字符的規(guī)則合并為一條規(guī)則。
具體細(xì)節(jié)參見代碼部分。
手動(dòng)模擬
按照題目的要求,分配多個(gè)字符數(shù)組,完成操作后,拼接在一起。
復(fù)雜度分析
時(shí)間復(fù)雜度:O(n)
空間復(fù)雜度:O(n)
注:上述的n為字符串的長度
代碼
數(shù)學(xué)規(guī)律
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1) return s;
int delta = numRows - 1;
int sz = s.size();
string rs;
// row 0
for (int i=0; i<sz; i+=2*delta)
rs.push_back(s[i]);
// row [1, numRows-1)
for (int row=1; row<numRows-1; ++row) {
int cur = 0; // 該行第幾個(gè)字符
int idx = row; // 對(duì)應(yīng)原先字符串的第幾個(gè)
while (idx<sz) {
if (cur%2 == 0) {
// row + 2*delta * (cur/2)
idx = row + delta * cur;
}
else {
// -row + 2*delta * ((cur+1)/2)
idx = -row + delta * (cur+1);
}
if (idx<sz)
rs.push_back(s[idx]);
++cur;
}
}
// row numRows-1
for (int i=numRows-1; i<sz; i+=2*delta)
rs.push_back(s[i]);
return rs;
}
};
手動(dòng)模擬
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1) return s;
vector<string> v_str = vector<string>();
for (int i=0;i<numRows;++i)
v_str.push_back(string());
int idx = 0; // 當(dāng)前字符的索引
int row = 0; // 將被填充的字符串索引
int dir = 1; // 方向:1 => 往下 -1 => 往上
int sz = s.size();
while (idx<sz) {
v_str[row].push_back(s[idx]);
row += dir;
if (row == 0)
dir = 1;
if (row == numRows-1)
dir = -1;
++idx;
}
string rs;
for (int i=0;i<numRows; ++i)
rs += v_str[i];
return rs;
}
};
廣告區(qū)域
本人和小伙伴們承接各種軟件項(xiàng)目,有需求的可以聯(lián)系我們。
QQ: 2992073083