个人感觉这就是一道找规律的题目,所以把规律找出来问题也就迎刃而解了。
两种方法,个人感觉算法本质是一样的,因为要遍历整个字符串,所以最小时间复杂度也是O(n)。
方法一:
由于是要一行一行存储,所以可以用一个字符串数组,大小为numRows,然后遍历字符串,把当前字符存到对应的行字符串中,最后一次连接每行的字符串。关键找到字符串的每个字符下标和对应行数的关系。
class Solution {
public:
string convert(string s, int numRows)
{
if(numRows<2 || s.size()<=numRows) return s;
vector<string> ans(numRows,"");//ans[i] = 第i+1行的字符串
int ci = 0;
while(ci<s.size())
{
for(int i=0;i<numRows && ci<s.size();)
{
ans[i++]+=s[ci++];
}
for(int i=numRows-2;i>0 && ci<s.size();)
{
ans[i--]+=s[ci++];
}
}
string res = "";
for(auto st:ans){
res+=st;
}
return res;
}
};
方法二:只用一个字符串变量存储结果,因此需要依次确定每行的字符串,找完规律你会发现,第一行和最后一行规律一样,剩下的行规律一样,因此要分开计算
class Solution {
public:
string convert(string s, int numRows)
{
if(numRows<2 || s.size()<=numRows) return s;
stringstream res;
int groupnumber = numRows*2-2;
for(int c=0;c<s.size();c+=groupnumber)
{
res<<s[c];
}
for(int r=1;r<numRows-1;++r)
{
for(int c=r;c<s.size();c+=r*2)
{
res<<s[c];
if(c<s.size() && (c+groupnumber-r*2) < s.size())
{
c+=(groupnumber-r*2);
res<<s[c];
}else break;
}
}
for(int c=numRows-1;c<s.size();c+=groupnumber)
{
res<<s[c];
}
return res.str();
}
};