一、概述
给出一个字符串,按格式输出。
模拟题,我的思路出现了错误,对于字符串的处理一直不能很好掌握。
虽然最后做出来了,但是时间和空间复杂度惨不忍睹。要哭出来。
看了别人的代码之后觉得自己就是一个傻逼。简直气死。
二、分析
1、我的思路
简直没得看,但是自己写的,还是说说吧。
第一眼看到这个题,以为是找规律,所以把字符串编号然后去看,规律很容易看出来,但是很难实现。因此这条路不通。
之前做PAT的时候有类似的题,把二叉树按Z字输出,那时候我用了队列和栈,因此在本题中我也尝试使用。
观察可知:
若将整个图形看做numRows层,那么偶数层使用队列,奇数层使用栈,然后组合。
因为使用队列和栈有点麻烦,因此我选择使用双端队列。
举例如下,以编号为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 numRows=5
则图形如下:
1...........9..............17
2......8..10.......16.18......24
3....7....11.....15...19....23
4..6......12..14......20..22
5..........13.............21
我们将第一列存在双端队列数组t的第一行;
第二三四列存在第二行;
第五列存在第三行;
第六七八列存在第四行;
第九列存在第五行;
第十十一十二存在第六行;
如下:
12345
678
910111213
141516
1718192021
222324
第一行和最后一行,选择奇数行的头输出;
其他行,选择奇数行的头和偶数行的尾输出。
如下:
1 9 17 // 2 8 10 16 18 24......
有一点要注意,如果最后一行是奇数,则一定要让其元素个数保证是numRows-2,否则会出错。
很麻烦也很不直观,但是能做出来,也仅止于此了。
2、较好的思路
与我的恰好相反,我是按列储存,人家是按行储存。
开一个string数组,共numRows行。
类似打印的方法,一个一个往里打印,模拟整个过程。
遍历s,按列一个一个存入数组,先正着存,再反着存,很是直观,如下:
abcdefghijklmn,numRows=5;
则a存在第一行,b在第二行......e在第五行,这时正着存;
然后f在第四行,g在第三行......i在第一行,这时反着存;
最后会发现,每一行就是对应的行的顺序。
然后接在一起输出即可。
没有想到这个方法主要是由于我没有想到可以一点一点接在后面,先加后减的方法,以为很复杂就放弃了。
三、总结
字符串处理,对于这种有正有反的情况,要熟练使用加加减减,确定正确的加减转换点,问题就容易许多。
PS:代码如下:
1、我的代码
#include<deque>
class Solution {
public:
string convert(string s, int numRows) {
if(numRows==1)
return s;
deque<char> q[1000];
int flag = 1;
int j = 0;
//string temp=s;
//cout<<temp<<"\n";
//s.erase(s.begin());
//s.erase(s.end());
//cout << s << "\n";
for (int i = 0; i<s.length(); i++)
{
if (flag == 1)
q[j].push_back(s[i]);
else
q[j].push_back(s[i]);
if (q[j].size() == numRows&&j % 2 == 0)
{
j++;
flag = 0;
}
if ((q[j].size() == numRows - 2) && j % 2 == 1)
{
j++;
flag = 1;
}
}
while(q[j].size()<numRows-2&&j%2==1)
{
q[j].push_back('#');
}
string ans;
int _j = 0;
while (ans.size() != s.size())
{
if (_j != 0 && _j != numRows)
{
for (int k = 0; k<=j; k++)
{
if (q[k].size() != 0)
{
if (k % 2 == 0)
{
ans = ans + (q[k].front());
q[k].pop_front();
//cout << ans << "\n";
}
else
{
if(q[k].back()!='#')
ans = ans + (q[k].back());
q[k].pop_back();
//cout << ans << "\n";
}
}
if (ans.size() == s.size())
return ans;
}
_j++;
}
else
{
for (int k = 0; k<=j; k++)
{
if (q[k].size() != 0)
{
if (k % 2 == 0)
{
ans = ans + (q[k].front());
q[k].pop_front();
//cout << ans << "\n";
}
}
if (ans.size() == s.size())
return ans;
}
_j++;
}
}
return ans;
}
};
2、较好的代码
class Solution {
public:
string convert(string s, int numRows) {
if(numRows==1)
return s;
string t[numRows];
for(int i=0;i<numRows;i++)
t[i]="";
int loc=0;
int flag=0;
for(int i=0;i<s.size();i++)
{
t[loc]+=s[i];
if(loc==0)
flag=0;
if(loc==numRows-1)
flag=1;
if(flag==0)
loc++;
if(flag==1)
loc--;
}
string ans="";
for(int i=0;i<numRows;i++)
ans+=t[i];
return ans;
}
};