依照特定轨迹遍历字符串图

题目大致是这样的,
字符串“PAYPALISHIRING”的一种“之”字型路线是这样的:
这里写图片描写叙述
假设一行一行的读写,就是PAHNAPLSIIGYIR。

所以,假设输入PAHNAPLSIIGYIR和3,就是横着的字符串和层数,输出N轨迹的字符PAYPALISHIRING。

首先想到的是怎样 将输入字符串。切割开来,比方上面是3层,分成3个字符串,这三个字符串一定是连续的
第一段+第二段+第三段
如今的难题是怎么推断每一段的长度。


将上面的图抽象化
这里写图片描写叙述
就是这样的,每个圆代表一个字符。这事实上是有规律的。

例如以下
这里写图片描写叙述
这样每一层的个数和这个周期之间是有关系的
base=(字符总个数/(层数+层数-2))
第一层个数=base+x
最后一层=base+x
其它层=base×2+x。
这里写图片描写叙述
这里面的x表示(如上图)绿色的圆的补偿,比方如以下4个绿色圆,
base=20/8=2
第一层=2+1=3;
第二层=2×2+1=5。
第三层=2×2+1=5;
第四层=2×2+1=5;
最后一层=2+0=2;
假设是以下这样的情况
这里写图片描写叙述
事实上算法也是一样的仅仅要对于补偿x值修正就能够了。本次就不讨论这样的情况了。


这里写图片描写叙述
到达这一步时,将之前的切割成了3部分,然后进行N轨迹遍历,
初步方案是。给三个字符串编号1、2、3.然后依照12321232123的遍历直到结束
所以如今须要解决的问题是,怎样实现这样的循环的遍历。

这里想到在cpu中有个寄存器用于决定地址是加一还是减一操作,所以借用这样的思想。例如以下方案
这里写图片描写叙述
实现函数例如以下

string  convert(string text,int nRow)//text为输入字符串 nRow是层数
{
 string r;
 vector <string> m;
 int arry[251]={0};
 int len=text.size();
 int s,c;
 s=len/(2*nRow-2);  //base数据
 c=len%(2*nRow-2);  //为上面绿色的个数
 for(int i=1;i<=nRow;++i)
 {
  if(i==1)    //计算第一层的个数
  {
   if(c>=1)
    arry[i]=s+1;    //arry的下标表述层数,内容为当前层的个数
   else
    arry[i]=s;
  }
  else if(i==nRow)  //计算最后一层的个数
  {
   if(c>=nRow)
    arry[i]=s+1;
   else
    arry[i]=s;
  }
  else      //中间层的个数
  {
   if(c>=i&&)
    arry[i]=2*s+1;
   else
    arry[i]=2*s;
  }
 }
 m.resize(nRow+1);
 int loc;
 int base;
 base=0;
 for(int i=1;i<=nRow;++i)   //依据每一层的个数,切割字符串
 {
  base+=arry[i-1];
  for(int j=0;j<arry[i];++j)
  {
   loc=j+base;
   m[i].push_back(text[loc]);//m[i]保存每一层的字符串。
  }
 }
 int flag=0;    //~0  addr++  0 add--   
 int cnt=1;
 int* num=new int[nRow+1]();
//以下是在切割完毕后的循环遍历
 int x,y;
 int tol=text.size();
 while(1)
 {
  tol--;
  if(tol<0)
   break;
  x=cnt;
  y=num[cnt];

  r.push_back(m[x][y]);
  num[cnt]++;
  if(cnt==nRow || cnt==1)
   flag=~flag;
  if(flag!=0)
   cnt++;
  else
   cnt--;
 }

 cout<<r<<endl;
 return r;
}
原文地址:https://www.cnblogs.com/cxchanpin/p/7221390.html